有没有办法避免这个Mockito测试的try / catch块?

时间:2016-09-16 14:33:07

标签: java lambda java-8 mockito

我正在使用Mockito来模拟一些对象并测试我的WebSocket邮件发件人服务。 send方法采用org.springframework.web.socket.WebSocketSession和消息,并返回CompletableFuture

在传递给thenAccept()的{​​{1}}方法的lambda中,我验证已使用期望值调用CompletableFuture方法:

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(),我被迫在lambda内部的调用周围添加一个无用的try / catch块。这是不必要的冗长。

我怎么能避免它?

4 个答案:

答案 0 :(得分:3)

您可以尝试使用Durian library

foodOnPlate.forEach(Errors.suppress().wrap(this::eat));
list.forEach(Errors.rethrow().wrap(c -> somethingThatThrows(c)));

或延伸Cosumer你自己

@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");
})

答案 1 :(得分:0)

我会以这种方式重做你的测试

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添加到测试方法签名。

此解决方案解决了两个问题:

  1. 您测试代码更清晰,所有断言和验证都在您的测试方法的最后一个地方;
  2. 解决方案解决竞争条件,当你测试可能会完成静音和绿色,但你CompletableFuture lambda中的玻璃化甚至已被执行

答案 2 :(得分:0)

从我的评论中继续,我会做这样的事情:

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());

答案 3 :(得分:-2)

这是重复吗? Java 8: Mandatory checked exceptions handling in lambda expressions. Why mandatory, not optional?

您在测试课程中,因此只需将throws IOException添加到您的方法中即可。这样,如果此方法引发IOException,则表示您的测试将失败。

或者你也可以说你的方法应该抛出IOException,

类似的东西:

@Test(expected = IOException.class)
public void yourTestCaser(){
   //... 

,它可能看起来像这样:

sender.sendStringMessage(session, "test text message").thenAccept(nil -> 
{ verify(session).sendMessage(expectedMessage); });