如何在 Mockito 中测试使用 ExecutorService 而不使用超时的代码?

Yak*_*sev 4 java junit unit-testing mockito

我有一堂课。

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

如何使用strategyByType.get(feedType).feed(feedDate, uuid)在调用 feed 方法时调用的Mockito进行验证?

@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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的版本。但我不想使用 Mockito 超时方法。在我看来,这不是一个好的解决方案。请帮帮我!

Per*_*uss 5

当我测试依赖于 executor 的代码时,我通常会尝试使用一个 executor 实现,该实现会立即在提交的同一线程中运行任务,以消除多线程的所有麻烦。也许您可以为您的FeedServiceImpl类添加另一个构造函数,让您提供自己的执行程序?谷歌番石榴库有一个MoreExecutors.directExecutor()方法可以返回这样的执行程序。这意味着您的测试设置将更改为:

service = new FeedServiceImpl(strategyByType, MoreExecutors.directExecutor());
Run Code Online (Sandbox Code Playgroud)

其余的测试代码应该可以正常工作,您可以安全地删除超时验证模式参数。