問題描述
我想測試以下方法:
public void dispatchMessage(MessageHandler handler, String argument1, String argument2, Long argument3) {
handler.registerMessage(() -> {
dispatcher.dispatch(argument1,
argument2,
argument3);
});
}
MessageHandler
是一個輔助類,它將接受 lambda 形式的功能接口實現,并將其存儲起來以供以后執行.
Where MessageHandler
is a helper class which will accept a Functional Interface implementation in the form a lambda, and store it for later execution.
有沒有辦法用 mockito 驗證被模擬的 MessageHandler
的 dispatchMessage
方法已被特定的 lambda 表達式調用:
Is there a way to verify with mockito that the dispatchMessage
method of the mocked MessageHandler
has been called with the specific lambda expression:
意思,我能不能寫這樣一個測試:
Meaning, can I write such a test:
@Test
public void testDispatchMessage_Success() throws Exception {
myMessageDispatcher.dispatchMessage(handler, "activityId", "ctxId", 1l, );
verify(handler, times(1)).dispatchMessage(() -> {
dispatcher
.dispatch("activityId", "ctxId", 1l,);
});
}
}
此測試將導致斷言錯誤:論據不同!通緝:
This test will result in assertion error: Argument(s) are different! Wanted:
......Tests$$Lambda$28/379645464@48f278eb
實際調用有不同的參數:
Actual invocation has different arguments:
..........Lambda$27/482052083@2f217633
這是有道理的,因為 mockito 試圖比較函數接口的兩個不同實現,它們具有不同的哈希碼.
which makes sense since mockito tries to compare two different implementations of the functional interface, which have a different hash code.
那么還有其他方法可以驗證方法 dispatchMessage()
是否已使用返回 void 的 lambda 調用,并且該方法的主體方法為dispatcher.dispatch("activityId", "ctxId", 1l,);
?
So is there some other way to verify that the method dispatchMessage()
has been called with a lambda that returns void and has a body method of
dispatcher.dispatch("activityId", "ctxId", 1l,);
?
推薦答案
是的,你可以.這里的訣竅是,您必須獲取傳遞給 registerMessage
的 lambda 實例,然后執行該表達式,然后您才能驗證結果.
Yes, you can. The trick here is that you have to get to the instance of the lambda that is passed to the registerMessage
and then execute that expression and then you can verify the result.
為了一個有意義的示例,我創建了這個 Handler
類,其中包含您要測試的 dispatchMessage
:
For the purpose of a meaningful example I created this Handler
class that contains the dispatchMessage
that you want to test:
public class Handler {
private Dispatcher dispatcher = new Dispatcher();
public void dispatchMessage(MessageHandler handler, String argument1, String argument2, Long argument3) {
handler.registerMessage(() -> {
dispatcher.dispatch(argument1,
argument2,
argument3);
});
}
interface MessageHandler {
void registerMessage(Runnable run);
}
static class Dispatcher {
void dispatch(String a, String b, long c){
// Do dispatch
}
}
}
您必須記住的是,lambda 表達式只是將函數傳遞給方法的簡寫形式.在這個例子中,函數是 Runnable
的 run
方法.因此,MessageHandler
接口的方法registerMessage
將Runnable
作為其參數.我還包含了 Dispatcher
的實現,它是從 registerMessage
中調用的.對此的測試如下所示:
What you have to remember is that a lambda expression is just a short hand form to pass a function to a method. In this example the function is the run
method of a Runnable
. Therefore the method registerMessage
of the interface for MessageHandler
takes a Runnable
as it's argument.
I also included an implementation for the Dispatcher
, which is called from within registerMessage
.
The test for this looks like this:
@RunWith(MockitoJUnitRunner.class)
public class HandlerTest {
@Mock
private Dispatcher dispatcher;
@InjectMocks
private Handler classUnderTest;
@Captor
private ArgumentCaptor<Runnable> registerMessageLambdaCaptor;
@Test
public void shouldCallDispatchMethod() {
final String a = "foo";
final String b = "bar";
final long c = 42L;
MessageHandler handler = mock(MessageHandler.class);
classUnderTest.dispatchMessage(handler, a, b, c);
verify(handler).registerMessage(registerMessageLambdaCaptor.capture());
Runnable lambda = registerMessageLambdaCaptor.getValue();
lambda.run();
verify(dispatcher).dispatch(a, b, c);
}
}
我們在 registerMessage
的第一次驗證中使用的 lambda 表達式有一個 ArgumentCaptor
.在驗證之后,我們可以從捕獲者那里檢索 lambda 表達式.lambda 表達式的類型是 Runnable
,在 MessageHandler
接口中定義.因此,我們可以對其調用 run
方法,然后驗證 Dispatcher
上的 dispatch
方法是否已使用所有適當的參數調用.
There is an ArgumentCaptor
for the lambda expression which we use in the first verification of the registerMessage
. After that verification we can retrieve the lambda expression from the captor. The type of the lambda expression is Runnable
, as defined in the MessageHandler
interface. Hence we can call the run
method on it and then verify that the dispatch
method on the Dispatcher
was called with all the appropriate arguments.
這篇關于Mockito 驗證特定的 lambda 已作為參數傳遞給 mock 的方法的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!