Mockito;模拟一个调用lamdba的方法,并验证该lambda调用的另一个模拟

时间:2019-02-22 00:31:59

标签: java lambda mocking mockito

我的问题,与此类似:

Using mockito; is it possible to mock a method that takes a lambda as a parameter and assert variables captured by the lambda?

但有足够的不同,我仍然需要一段时间才能弄清楚:

如何验证在lamdba中使用的由模拟调用的方法是否已传递给另一个模拟对象的方法?

这似乎有些令人费解,但是在Java 8库(例如JDBI)中经常发生这种情况,例如,您有一个JDBI对象:

JDBI MyDBConnection

你应该嘲笑。然后将其与withHandle方法一起使用,以传递实现HandleCallback 类型的lamdba:

//code I'm testing. I implement the lamdba, and want to verify it
//calls the correct method in dao provided by JDBI.
MyDBConnection.withHandle(
    (handle) -> { ... handle.attach(SomeDao.class).findSomethingInDB(args) .. }

推荐使用哪种方法

所以我想验证是否调用了findSomethingInDB(eq(args))。

就像我说的那样,这是相似的,但又足够不同,至少在以后的某个时候,当我忘记如何做时,我会发现这个答案很有价值。因此,调用我的lamdba的原始第3方库方法的处理方式与上面提到的问题中给出的答案类似,但有一些调整:

when(JDBIMock.withHandle(any())).then(
  //Answer<Void> lambda
  invocationOnMock -> {
     Object[] args = invocationOnMock.getArguments();
     assertEquals(1, args.length);
     //the interface def for the callback passed to JDBI
     HandleCallback lamdba = (HandleCallback) args[0];
     when(mockHandle.attach(SomeDao.class)).thenReturn(mockDao);
     //this actually invokes my lambda, which implements the JDBI interface, with a mock argument
     lambda.withHandle(mockHandle);
     //bingo!
     verify(mockDao).findSomethingInDB(eq(args));
  }
)

2 个答案:

答案 0 :(得分:0)

看到问题,应该在上面充分回答;)

答案 1 :(得分:0)

我正在尝试做一个非常相似的事情,即在测试中的模拟JDBI调用中验证从withHandle传递给另一个模拟的参数。

您在问题中给出的答案为我指明了正确的方向,但给了我错误消息:

The method then(Answer<?>) in the type OngoingStubbing<Object> is not applicable for the arguments ((<no type> invocationOnMock) -> {})

相反,我不得不使用传递给org.mockito.stubbing.Answer的新then,类似于您链接到的另一个问题。

在您的示例中,这类似于:

when(JDBIMock.withHandle(any())).then(
  //Answer<Void> lambda
  new Answer<Void>() {
    @Override
    public Void answer(InvocationOnMock invocation) throws Throwable {
      Object[] args = invocation.getArguments();
      assertEquals(1, args.length);
      //the interface def for the callback passed to JDBI
      HandleCallback lambda = (HandleCallback) args[0];
      when(mockHandle.attach(SomeDao.class)).thenReturn(mockDao);
      //this actually invokes my lambda, which implements the JDBI interface, with a mock argument
      lambda.withHandle(mockHandle);
      //bingo!
      verify(mockDao).findSomethingInDB(eq(args));

      return null; // to match the Void type
    }
  }
)

在我的情况下,我期望从withHandle获得结果列表,因此必须更改Answer类型,并返回answer的类型以匹配并返回虚拟列表而不是{ {1}}。 (返回的实际结果在此测试中无关紧要,只是预期的参数已传递给我的后续模拟对象)

我还将Void之外的verify调用移到了测试的主体中,因此很明显,这是对测试的期望,而不是模拟设置的一部分。