如何模拟构造函数中的属性设置



假设我有一个具有以下构造函数的类:

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。方法被调用了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指定构造函数。然而,到PowerMockito.mockStatic(Executors.class)时,MyImpl的构造函数已经通过"真正的"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在到达构造函数时不知何故是空的。

问题在于MyImpl的设计。

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

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

然后,您已经准备好了将普通mock与普通ExecutorService mock一起使用。

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

你可以尝试这样做,

@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);
}

//测试

相关内容

  • 没有找到相关文章

最新更新