java mockit验证特定的lambda是否已作为mock方法中的参数传递

mzillmmw  于 2023-01-01  发布在  Java
关注(0)|答案(3)|浏览(179)

我想测试以下方法:

public void dispatchMessage(MessageHandler handler, String argument1, String argument2, Long argument3) {

    handler.registerMessage(() -> {
        dispatcher.dispatch(argument1,
                argument2,
                argument3);
    });

}

其中MessageHandler是一个helper类,它将接受lambda形式的函数接口实现,并将其存储以供以后执行。
是否有一种方法可以使用mockito验证是否使用特定的lambda表达式调用了被模拟的MessageHandlerdispatchMessage方法:
意思是,我可以写这样一个测试:

@Test
public void testDispatchMessage_Success() throws Exception {

    myMessageDispatcher.dispatchMessage(handler, "activityId", "ctxId", 1l, );

    verify(handler, times(1)).dispatchMessage(() -> {
        dispatcher
            .dispatch("activityId", "ctxId", 1l,);
    });

}

}

此测试将导致Assert错误:参数不同!需要:

......Tests$$Lambda$28/379645464@48f278eb

实际调用具有不同的参数:

..........Lambda$27/482052083@2f217633

这是有意义的,因为Mockito试图比较具有不同散列码的函数接口的两个不同实现。
那么,是否有其他方法可以验证方法dispatchMessage()是否已经被一个返回void的lambda调用,并且其主体方法为dispatcher.dispatch("activityId", "ctxId", 1l,);

lnlaulya

lnlaulya1#

是的,你可以,这里的技巧是你必须得到lambda的示例,它被传递给registerMessage,然后执行那个表达式,然后你可以验证结果。
为了提供一个有意义的示例,我创建了这个Handler类,其中包含您要测试的dispatchMessage

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表达式只是一个传递函数到方法的简写形式。在这个例子中函数是Runnablerun方法。因此MessageHandler接口的registerMessage方法接受Runnable作为它的参数。我还包含了Dispatcher的实现。它是从registerMessage中调用的。测试如下所示:

@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。因此,我们可以在它上面调用run方法,然后验证在Dispatcher上调用dispatch方法时是否使用了所有适当的参数。

eeq64g8w

eeq64g8w2#

你想要计算lambda argThat(a -> a.get(),然后才比较它的值:

when(dogObject.barkAt(argThat(a -> a.get().equals(PEOPLE_TO_BARK_AT)))).thenReturn(OUTCOME);
i5desfxk

i5desfxk3#

在特定的lambda之外,你可以验证你的方法是用任意lambda表达式调用的,如下所示:

verify(handler).registerMessage(any())

    private fun <T> any(): T {
        Mockito.any<T>()
        return null as T
    }

相关问题