如何在构造函数中模拟 属性 集
How to mock property set in constructor
假设我有一个 class 具有以下构造函数:
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);
}
这个 class 某处有以下方法:
@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 指定构造函数。然而,到我PowerMockito.mockStatic(Executors.class)
的时候,MyImpl的构造函数已经通过"real"Executors.newFixedThreadPool
.
创建了自己的executor
知道如何解决这个问题吗?
更新:
显然改变设计没什么大不了的,我现在有以下内容:
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。
问题出在MyImpl
的设计上。
与其在构造函数中创建线程池执行器,不如传递给它。您可以为当前的构造函数放置一个静态工厂方法,这样您仍然可以使用与现在使用的参数相同的参数创建实例。
为什么需要转换为 ThreadPoolExecutor
?这使您可以依赖特定的实现。如果你不需要这个,你最好使用 java.util.concurrent.ExecutorService
.
然后你就可以使用带有普通 ExecutorService
mock 的普通 mockito 了。
我猜问题是你的 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);
}
//测试
假设我有一个 class 具有以下构造函数:
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);
}
这个 class 某处有以下方法:
@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 指定构造函数。然而,到我PowerMockito.mockStatic(Executors.class)
的时候,MyImpl的构造函数已经通过"real"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。
问题出在MyImpl
的设计上。
与其在构造函数中创建线程池执行器,不如传递给它。您可以为当前的构造函数放置一个静态工厂方法,这样您仍然可以使用与现在使用的参数相同的参数创建实例。
为什么需要转换为 ThreadPoolExecutor
?这使您可以依赖特定的实现。如果你不需要这个,你最好使用 java.util.concurrent.ExecutorService
.
然后你就可以使用带有普通 ExecutorService
mock 的普通 mockito 了。
我猜问题是你的 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);
}
//测试