Abstract:
I have a Spring @Component
that uses an autowired ExecutorService as a work pool. I'm using JUnit and Mockito to test the functionality of the component and I need to mock that Executor Service. This has been trivial for other autowired members - a generic helper, and a DAO layer for instance are easily mocked, but I need a real Executor Service.
Code:
@RunWith(MockitoJUnitRunner.class)
public class MadeUpClassNameTest{
@Mock
private ExecutorService executor;
@Before
public void initExecutor() throws Exception{
executor = Executors.newFixedThreadPool(2);
}
@InjectMocks
private ASDF componentBeingAutowired;
...
This alone doesn't work, the results of invokeAll()
is always an empty list.
Attempting to more explicitly mock the executor method also doesn't work...
@Test
public void myTestMethod(){
when(executor.invokeAll(anyCollection()))
.thenCallRealMethod();
...
}
I get the cryptically worded exception:
You cannot use argument matchers outside of verification or stubbing.
(I thought this was a stubbing ?)
I could provide a thenReturn(Answer<>)
method, but I'd like to make sure that the code actually works with an executor, a fair bit of the code is devoted to mapping the results of Futures.
Problem How do I provide a real (or functionally usable mock) Executor Service ? Alternatively, is my difficulty in testing this component a sign that this is a poor design in need of refactoring, or possibly a bad test scenario ?
Notes I want to stress that my problem is NOT getting Mockito or Junit set up. Other mocks and tests work correctly. My problem is specific only to the particular mock above.
Using: Junit 4.12, Mockito 1.10.19, Hamcrest 1.3
I think the following code runs after the Mock is injected.
@Before
public void initExecutor() throws Exception{
executor = Executors.newFixedThreadPool(2);
}
This causes your local copy of executor
to be set, but not the one that is injected.
I would recommend using constructor injection in on your componentBeingAutowired
and create a new one in your unit test and exclude Spring dependencies. Your test could then look like something below:
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
}
}
Another way is to use ReflectionTestUtils
to inject the executor
@Before
public void initExecutor() {
ReflectionTestUtils.setField(componentBeingAutowired, "executor", Executors.newFixedThreadPool(2);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With