我正在使用Mockito模拟一些对象并测试我的WebSocket消息发送器服务。send方法接受一个org.springframework.web.socket.WebSocketSession
和一个消息,并返回一个CompletableFuture
。
在传递给CompletableFuture
的thenAccept()
方法的lambda中,我验证了session.sendMessage()
方法已被使用期望值调用:
WebSocketSession session = mockWebSocketSession();
TextMessage expectedMessage = new TextMessage("test text message");
sender.sendStringMessage(session, "test text message").thenAccept(nil -> {
try{ // this is what I am talking about
verify(session).sendMessage(expectedMessage);
}catch(IOException e){}
});
由于sendMessage()
方法抛出IOException
,我被迫在lambda内部的调用周围添加一个无用的try/catch块。这是不必要的啰嗦。
您可以尝试使用榴莲库
foodOnPlate.forEach(Errors.suppress().wrap(this::eat));
list.forEach(Errors.rethrow().wrap(c -> somethingThatThrows(c)));
或扩展consumer self
@FunctionalInterface
public interface ThrowingConsumer<T> extends Consumer<T> {
@Override
default void accept(final T elem) {
try {
acceptThrows(elem);
} catch (final Exception e) {
/* Do whatever here ... */
System.out.println("handling an exception...");
throw new RuntimeException(e);
}
}
void acceptThrows(T elem) throws Exception;
}
//and then pass
thenAccept((ThrowingConsumer<String>) aps -> {
// maybe some other code here...
throw new Exception("asda");
})
我将以这种方式重做您的测试
final String testMessage = "test text message";
WebSocketSession session = mockWebSocketSession();
sender.sendStringMessage(session, testMessage).get(); // will wait here till operation completion
verify(session).sendMessage(new TextMessage(testMessage));
并将IOException
添加到测试方法签名中。
这个解决方案解决了两个问题:
- 你的测试代码更干净,所有的断言和验证都在你的测试方法的末尾在一个地方;
- 解决方案解决了竞争条件,当您的测试可能无声地完成并且绿色,但您在
CompletableFuture
lambda中的玻璃化甚至被执行
根据我的评论,我将做这样的事情:
public void myMethod() {
try{ // this is what I am talking about
verify(session).sendMessage(expectedMessage);
}catch(IOException e) {}
}
然后:
sender.sendStringMessage(session, "test text message").thenAccept(nil -> myMethod());
复制这个?Java 8: lambda表达式中的强制检查异常处理。为什么是强制性的,而不是可选的?
您在测试类中,因此只需将throws IOException
添加到您的方法。这样,如果这个方法引发IOException,在这种情况下,它意味着你的测试将失败。
或者你也可以说你的方法预计会抛出IOException,
类似于:
@Test(expected = IOException.class)
public void yourTestCaser(){
//...
有了这个,它看起来像这样:
sender.sendStringMessage(session, "test text message").thenAccept(nil ->
{ verify(session).sendMessage(expectedMessage); });