Hot questions for Using Mockito in executorservice

Top 10 Java Open Source / Mockito / executorservice

Question:

I have a class.

public class FeedServiceImpl implements FeedService {
    private final Map<FeedType, FeedStrategy> strategyByType;
    private final ExecutorService executorService = Executors.newSingleThreadExecutor(); 

    public FeedServiceImpl(Map<FeedType, FeedStrategy> strategyByType) {
        if (strategyByType.isEmpty()) throw new IllegalArgumentException("strategyByType map is empty");
        this.strategyByType = strategyByType;
    }

    @Override
    public void feed(LocalDate feedDate, FeedType feedType, String uuid) {
        if (!strategyByType.containsKey(feedType)) {
            throw new IllegalArgumentException("Not supported feedType: " + feedType);
        }
        executorService.submit(() -> runFeed(feedType, feedDate, uuid));
    }


    private FeedTaskResult runFeed(FeedType feedType, LocalDate feedDate, String uuid) {
        return strategyByType.get(feedType).feed(feedDate, uuid);
    }
}

How can I verify with Mockito that strategyByType.get(feedType).feed(feedDate, uuid) was called when I call feed method?

@RunWith(MockitoJUnitRunner.class)
public class FeedServiceImplTest {
    private LocalDate date = new LocalDate();
    private String uuid = "UUID";

    private FeedService service;
    private Map<FeedType, FeedStrategy> strategyByType;

    @Before
    public void setUp() {
        strategyByType = strategyByTypeFrom(TRADEHUB);
        service = new FeedServiceImpl(strategyByType);
    }

    private Map<FeedType, FeedStrategy> strategyByTypeFrom(FeedSource feedSource) {
        return bySource(feedSource).stream().collect(toMap(identity(), feedType -> mock(FeedStrategy.class)));
    }

    @Test
    public void feedTest() {
        service.feed(date, TH_CREDIT, uuid);
        verify(strategyByType.get(TH_CREDIT), timeout(100)).feed(date, uuid);
    }
}

This is my version. But I don't want to use Mockito timeout method. It's in my opinion not a good solution. Help me please!


Answer:

When I test code that are dependent on executors I usually try to use an executor implementation that runs the task immediately in the same thread as submitted in order to remove all the hassle of multithreading. Perhaps you can add another constructor for your FeedServiceImpl class that lets you supply your own executor? The google guava lib has a MoreExecutors.directExecutor() method that will return such an executor. That would mean your test setup would change to something like:

service = new FeedServiceImpl(strategyByType, MoreExecutors.directExecutor());

The rest of the test code should then work as it is, and you can safely drop the timeout verification mode parameter.

Question:

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


Answer:

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
    }
}

Question:

How can I mock executorService.submit() in the below scenerio. I have to mock

cacheController.someMethod(); but as submit method is called it creates a thread and cacheController.someMethod(); never gets called for test class.

@Autowired
CacheController cacheController;
protected static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(1);

EXECUTOR.submit(() -> {
        try {
            cacheController.someMethod();
        } catch (Exception e) {
            e.printStackTrace();
        }
    });

Answer:

Basically you created hard to test code by relying on

protected static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(1);

In order to test that, you would have to use PowerMock(ito) dark magic to gain control over that call to the static method newFixedThreadPool(1) here. In theory, that is nice and see, see here for example.

But: typically, when you do decent unit testing for Spring based environments, then you are probably already using another test runner, to get that @AutoWired thing working in your test setup. Adding PowerMock(ito) to that makes things much more complicated, and prone to errors.

Thus, the real answer is: rework your design, to not rely on that static method call. If you turn that thing into a normal field, you should be able to use "standard" mockito injection mechanisms, like outlined here.

Finally: I would also suggest to look into a same thread executor. Meaning: dont mock the service, but inject a specific service instance that simply calls your code on the same thread. Then you get quite more test coverage, but you avoid the most multi threading issues that normally give headaches in unit tests.

Question:

I am trying to unit test a code run containing executor service where the api is getting called twice or more depending on the no of devices in the list. When I try to unit test this from console, Mockito verify fails throwing an error that the Api is called only once while I passed list of devices. However, when I debug in intellij, it works correctly and gets executed and verified according to the no of devices in the list.

Following is the code

final ExecutorService executor = new ThreadPoolExecutor(MAX_THREADS,
    TimeUnit.MILLISECONDS,
    new LinkedBlockingQueue<Runnable>());

DeviceList.stream().forEach(device -> executor.execute(() ->
    GatewayToTest.deliver(device, id, testObject)));

Unit test code:

verify(GatewayToTest, times(devices.size()))
    .deliver(any(Device.class), anyString(), any(TestObject.class));

In the above code, GatewayToTest is called only once when I run unit tests in console.


Answer:

The executions run asynchronously, so you cannot guarantee that all the calls to GatewayToTest.deliver happen before verify. Try to await for termination after submitting the tasks for execution:

executor.awaitTermination(10,TimeUnit.SECONDS);

Question:

How to write test case using mockito and junit for ExecuterService?

protected void updateRequest(String request) {

      ExecutorService executor = Executors.newFixedThreadPool(1);
      executor.submit(() -> {
          service.callGattuService(request);
      });

      executor.shutdown();
}

Earlier this method was not Multithreaded and service.callGattuService() was called directly and following was test case.

@Test 
   public void updateGattu() throws SystemException, SocketException, IOException {
      when(service.callGattuService("11")).thenReturn(something); 

      testSubject.updateRequest(request)

      verify(service, times(1)).callGattuService("11");
   }

I am not sure how to manipulate it so that ExecuterService can be detected/called.


Answer:

The simplest and straightforward solution in this situation is adding delay before verification without changing test logic because you're already checking that the internal method was called with particular argument no matter through executor or not.

@Test 
public void updateGattu() throws SystemException, SocketException, IOException {
    testSubject.updateRequest("11")
    verify(service, after(2*1000).times(1)).callGattuService("11");
}

Don't forget to spy your service. Hope it helps!

Edit: In the previous version of mockito-all (1.9.5) here is similar Mockito.timeout(int) method which could be used like so

@Test 
public void updateGattu() throws SystemException, SocketException, IOException {
    testSubject.updateRequest("11")
    verify(service, timeout(2*1000)).callGattuService("11");
}