Java 消费者模拟法

Java 消费者模拟法,java,lambda,mocking,Java,Lambda,Mocking,我想在此源代码中模拟repository.ActionFile(字符串路径,使用者操作): @Autowired private FileRepositoryService repository; public Document getDocument(URL url) { MutableObject<Document> obj = new MutableObject<>(); Consumer<InputStream> actionOnFi

我想在此源代码中模拟repository.ActionFile(字符串路径,使用者操作):

@Autowired
private FileRepositoryService repository;

public Document getDocument(URL url) {
    MutableObject<Document> obj = new MutableObject<>();
    Consumer<InputStream> actionOnFile = inputStream -> obj.setValue(getDocument(inputStream));
    try {
        repository.actionOnFile(url.toExternalForm(), actionOnFile);
    } catch (S3FileRepositoryException e) {
        throw e.getCause();
    }
    return obj.getValue();
}
@Autowired
私有FileRepositoryService存储库;
公共文档getDocument(URL){
MutableObject obj=新的MutableObject();
消费者操作onfile=inputStream->obj.setValue(getDocument(inputStream));
试一试{
actionOnFile(url.toExternalForm(),actionOnFile);
}捕获(S3FileRepositoryException e){
抛出e.getCause();
}
返回obj.getValue();
}
问题是第二个参数是lambda表达式


如何用mockito模拟它,我需要将输入流传递给
accept
方法来测试它

如果您只想模拟函数参数,那么以下操作将起作用:

Mockito.when(convertStringtoInt(Mockito.any(String.class), Mockito.any(Consumer.class))).then[...]
如何用mockito模拟它,我需要通过accept方法测试 输入流

在本例中,您需要测试
getDocument()
方法。
因此,需要模拟的是被测试类的依赖关系: 这是
存储库
字段。
actionfile.add()
更具体地说应该是模拟的。
根据您的代码,要么该方法应抛出
S3FileRepositoryException
,要么引发代码中看不到的副作用。

在异常场景中,您应该编写如下内容:

 Mockito.when(fileRepositoryServiceMock.actionOnFile(url.toExternalForm(), actionOnFile)).thenThrow(new S3FileRepositoryException(cause));
在成功的情况下,您只需验证是否调用了该方法:

 Mockito.verify(fileRepositoryServiceMock).actionOnFile(url.toExternalForm(), actionOnFile));
嘲笑
消费者
真的没什么大不了的。
它是一个接口,您可以用Mockito模拟任何接口。

真正的问题实际上是
消费者
没有成为测试方法的API的一部分。
它是一个局部变量。
此外,它依赖于代码中未显示的
inputStream
字段。
你不能也不必嘲笑内心的东西。
请注意,它还依赖于未模拟的重载
getDocument()
方法。
因此,如果希望
getDocument()
接受InputStream而不引发异常,则需要提供一致的
InputStream

长话短说:我认为您应该重新考虑您的设计,在另一个类中提取依赖的进程,或者编写一个集成测试。
我找到了解决方案

doAnswer(ans -> {
    Consumer<InputStream> callback = (Consumer<InputStream>) ans.getArguments()[1];
    InputStream stream = new ByteArrayInputStream(
            "test".getBytes(StandardCharsets.UTF_8.name()));
    callback.accept(stream);
    return null;
}).when(repository).actionOnFile(eq("any"), any(Consumer.class));
doAnswer(ans->{
使用者回调=(使用者)ans.getArguments()[1];
InputStream=新的ByteArrayInputStream(
“test”.getBytes(StandardCharsets.UTF_8.name());
callback.accept(流);
返回null;
}).when(repository.actionfile(eq(“any”)、any(Consumer.class));

您可能需要重构服务以接受
函数
并返回
R
。我假设你们成为消费者之后关闭了输入流,但你们的问题恰恰是当你们的服务依赖于一些副作用来产生任何结果时会发生什么。我认为你们应该接受你们自己的答案。虽然它并不漂亮,但这也是测试您在getDocument方法中内联定义的ActionFile使用者所需要做的(请建议更漂亮的解决方案)抱歉,我也不知道。用Mockito写这篇文章不是很自然的事。在我的项目中,我将所有凌乱的代码移到一个单独的函数中,并给它起了一个漂亮的名字:)