如何在构造函数中模拟属性集

时间:2016-11-17 15:12:37

标签: java spring unit-testing mockito powermock

让我说我有一个带有以下构造函数的类:

public class MyImpl extends Abstract<Foo> {

    @Autowired
    private FooClass foo;

    private final ThreadPoolExecutor executor;

    public MyImpl(String name, int num) {
        super(name);
        this.executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(num);

    }

这个类的某个地方有以下方法:

    @Override
    public void doThis() {
        for (int i = 0; i < num; i++) {
            executor.execute(() -> foo.doMethod());
        }
        executor.shutdown();

        super.doThis();
    }

现在,我想测试foo.doMethod被调用了4次executor.execute(any())executor.shutdown()被调用了4次。

到目前为止我已经

@RunWith(PowerMockRunner.class)
@PrepareForTest(Executors.class)
public class MyImplTest {

    private static final int NUM = 4;

    @Mock
    private FooClass foo;
    @Mock
    private ThreadPoolExecutor executor;
    @InjectMocks
    private MyImpl imyImpl = new MyImpl("Name", NUM);

    @Test
    public void shouldCallFourTimes() throws Exception {
        PowerMockito.mockStatic(Executors.class);
        when(Executors.newFixedThreadPool(NUM)).thenReturn(foo);

        myImpl.doThis();

        PowerMockito.verifyStatic();
        Executors.newFixedThreadPool(NUM);
        verify(foo, times(NUM)).doMethod());

    }

然而这不起作用。 Mockito说与我的模拟执行官没有任何互动。 由于@Autowired依赖项不是构造函数的一部分,我需要使用@InjectMocks在字段中指定构造函数。然而,到I PowerMockito.mockStatic(Executors.class)时,MyImpl的构造函数已经通过&#34; real&#34;创建了自己的执行器。 Executors.newFixedThreadPool

知道如何解决这个问题吗?

更新: 显然,改变设计并不是什么大问题,我现在有以下几点:

public class MyImpl extends Abstract<Foo> {

    @Autowired
    private FooClass foo;

    private final ThreadPoolExecutor executor;

    public MyImpl(String name, ThreadPoolExecutor executor) {
        super(name);
        this.executor = executor;
}

试验:

@Mock
private ThreadPoolExecutor executor;
@InjectMocks
private MyImpl imyImpl = new MyImpl("Name", executor);

但是,当到达构造函数时,executor以某种方式为null。

2 个答案:

答案 0 :(得分:4)

问题在于MyImpl

的设计

不应在构造函数中创建线程池执行器,而应将其传递给它。您可以为当前的构造函数放置一个静态工厂方法,这样您仍然可以使用现在使用的相同参数创建实例。

为什么需要演员ThreadPoolExecutor?这使您可以依赖于特定的实现。如果你不需要这个,你最好使用java.util.concurrent.ExecutorService

然后你就可以使用普通的ExecutorService模拟使用普通的mockito。

答案 1 :(得分:0)

我想问题就是你的模拟类没有被注入,

你可以尝试这样的事情,

@Mock
private FooClass foo;
@Mock
private ThreadPoolExecutor executor;

private MyImpl imyImpl;

@Before
public void setUp() throws Exception {
   imyImpl = new MyImpl("Name", NUM);
   impl.setFoo(foo);
   impl.setExecutor(executor);
}

//测试