Powermock mocking constructor через whennew() не работает с анонимным классом

У меня есть класс DummyResource и файл DummyTarget и тестовый класс TestDummyResource, как показано ниже, но вымышленный объект DummyResource dr = mock(DummyResource.class) работает только при вызове конструктора внутри обычного класса, когда он вызывал анонимный класс, вызывающий фактический конструктор вместо того, чтобы использовать насмешливый объект.

Версии:

powermock 1.4.12 mockito 1.9.0 junit 4.8.2

DummyTarget.java:

import java.io.IOException;
import java.io.OutputStream;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;


public class DummyTarget {
    public StreamingOutput testMocking() {
        return new StreamingOutput() {
            @Override
            public void write(OutputStream arg0) throws IOException, WebApplicationException {
                new DummyResource();
            }
        };
    }
}

DummyResource.java:

package com.smin.dummy;

public class DummyResource {
    public DummyResource() {
        System.out.println("mock failure");
    }
}

TestDummyResource.java:

package com.smin.dummy;

import static org.mockito.Mockito.mock;

import java.io.IOException;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.StreamingOutput;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest({DummyResource.class,DummyTarget.class})
public class TestDummyResource  {

    @Before
    public void setUp() throws Exception {
        DummyResource dr = mock(DummyResource.class);
        PowerMockito.whenNew(DummyResource.class).withNoArguments().thenReturn(dr);
    }

    @Test
    public void testMocked() throws WebApplicationException, IOException {
        new DummyResource(); // it uses the mocked object dr here, 
                             //doesn't print "mock failure"
        StreamingOutput sop = new DummyTarget().testMocking();
        sop.write(null);     // it calls DummyResource constructor,
                             // prints ""mock failure"" here
    }
}

Ответы

Ответ 1

Похоже, что анонимный класс может наследовать пакет класса, который его определяет. Можете ли вы попробовать подстановочную форму PrepareForTest?:

@PrepareForTest("com.smin.dummy.*")

Если это не сработает, вы можете попробовать дробовик PrepareEverythingForTest Аннотация.

Ответ 2

Вам нужно подготовить класс, вызывающий конструктор, а не класс, на котором вызывается конструктор, следующее должно исправить вас:

@PrepareForTest(DummyTarget.class)

Для получения дополнительной информации проверьте эту страницу.

Ответ 3

На самом деле вам нужно подготовиться к тестированию класса, который вызывает вызов конструктора, а не класса, на котором был вызван конструктор. См. https://github.com/jayway/powermock/wiki/MockConstructor.

В вашем случае вы должны использовать @PrepareForTest (DummyTarget.class)

Ответ 4

У меня была такая же проблема, и я разрешил ее с использованием whenNew с полным именем. Полноценное имя внутреннего анонимного класса в вашем случае:

DummyTarget.class + "$1"

поэтому вы должны создать макет этого класса:

DummyResource dr = mock(Class.forName(DummyTarget.class + "$1"));

и он будет работать для вас.

Кроме того, не забудьте подготовить класс DummyTarget:

@PrepareForTest(DummyTarget.class)

Надеюсь, что это помогло =]