摘要:
我有一个 Spring
@Component
,它使用自动装配的 ExecutorService 作为工作池。我正在使用 JUnit 和 Mockito 来测试组件的功能,并且我需要模拟该执行程序服务。这对于其他自动装配的成员来说是微不足道的 - 例如,通用帮助程序和 DAO 层很容易被嘲笑,但我需要一个realExecutorService。
代码:
@RunWith(MockitoJUnitRunner.class)
public class MadeUpClassNameTest{
@Mock
private ExecutorService executor;
@Before
public void initExecutor() throws Exception{
executor = Executors.newFixedThreadPool(2);
}
@InjectMocks
private ASDF componentBeingAutowired;
...
仅此是行不通的,
invokeAll()
的结果始终是一个空列表。
尝试更明确地模拟执行器方法也不起作用......
@Test
public void myTestMethod(){
when(executor.invokeAll(anyCollection()))
.thenCallRealMethod();
...
}
我得到了措辞神秘的例外:
您不能在验证或存根之外使用参数匹配器。
(我以为这是一个存根?)
我可以提供一个
thenReturn(Answer<>)
方法,但我想确保代码实际上可以与执行器一起使用,相当多的代码专门用于映射Futures的结果。
问题 如何提供真实的(或功能上可用的模拟)执行器服务?或者,我在测试这个组件时遇到困难是否表明这是一个需要重构的糟糕设计,或者可能是一个糟糕的测试场景?
注意事项 我想强调的是,我的问题不是设置 Mockito 或 Junit。其他模拟和测试工作正常。我的问题仅针对上面的特定模拟。
使用:Junit 4.12、Mockito 1.10.19、Hamcrest 1.3
我认为注入 Mock 后会运行以下代码。
@Before
public void initExecutor() throws Exception{
executor = Executors.newFixedThreadPool(2);
}
这会导致设置
executor
的本地副本,但不会设置注入的副本。
我建议在您的 componentBeingAutowired
中使用
构造函数注入并在单元测试中创建一个新的并排除 Spring 依赖项。您的测试可能如下所示:
public class MadeUpClassNameTest {
private ExecutorService executor;
@Before
public void initExecutor() throws Exception {
executor = Executors.newFixedThreadPool(2);
}
@Test
public void test() {
ASDF componentBeingTested = new ASDF(executor);
... do tests
}
}
另一种方法是使用
ReflectionTestUtils
将执行器注入到名为 executor 的注入字段中
@Before
public void initExecutor() {
ReflectionTestUtils.setField(componentBeingAutowired, "executor", Executors.newFixedThreadPool(2));
}
您可以使用@Spy注释。
@RunWith(MockitoJUnitRunner.class)
public class MadeUpClassNameTest{
@Spy
private final ExecutorService executor = Executors.newFixedThreadPool(2);
....
}
您可以使用@Spy注释。
@RunWith(MockitoJUnitRunner.class)
public class MadeUpClassNameTest{
@Spy
private final ExecutorService executor = Executors.newFixedThreadPool(2);
@Test
...
}