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!
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.
A little improvement for @Per Huss answer so you won't have to change your constructor you can use ReflectionTestUtils class which is part of the spring-test package.
@Before
public void setUp() {
strategyByType = strategyByTypeFrom(TRADEHUB);
service = new FeedServiceImpl(strategyByType);
ReflectionTestUtils.setField(service , "executorService", MoreExecutors.newDirectExecutorService());
}
Now in the tests your executorService will implement the MoreExecutors.newDirectExecutorService() and not Executors.newSingleThreadExecutor().
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