我正在尝试测试写为lambda的RabbitTemplate#convertAndSend方法,就像这样:
// other stuff omitted for brevity
rabbitTemplate.convertAndSend(myQueue, jsonString, message -> {
message.getMessageProperties().setPriority(priority);
return message;
});
// other stuff omitted for brevity
我要尝试的测试用例是使用ArgumentCaptor
的情况,以验证是否使用正确的参数调用了该方法。
@Test
public void givenMyNotification_whenElementIsSent_thenSetPriorityAndSendValidParameters() {
final ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
final int expectedPriority = 5;
final Notification expected = TestUtils.getNotification();
testClass.handleNotification(expected);
verify(rabbitTemplate).convertAndSend(captor.capture(), captor.capture(),
ArgumentMatchers.eq(MessagePostProcessor.class));
// assertThat...
));
}
由于参数不同,测试在验证步骤失败。
Wanted:
<Capturing argument>,
<Capturing argument>,
interface org.springframework.amqp.core.MessagePostProcessor
Actual invocation:
"myQueue",
"myJson",
com.example.notification.service.NotificationService$$Lambda$5/73698537@5bda80bf
我已经尝试过其他一些来自Matchito和hamcrest的Matchers,但无济于事。
所以,我的问题是:
一个人如何测试这种事情?
这是否是一种很好的做法,或者还有其他/更好的方法来测试兔子模板的发送吗?
答案 0 :(得分:1)
除了最后一个匹配项ArgumentMatchers.eq(MessagePostProcessor.class)
以外,您几乎都可以接受。
您实际上要求 Mockito 将等同性匹配到该参数的类。 您应该匹配:
ArgumentMatchers.any(MessagePostProcessor.class)
的参数类型ArgumentMatchers.eq(expectedMessageProcessor)
(如果您碰巧拥有的话)但是在这种特殊情况下,如果使用第一个选项,则可能会遇到编译器问题,因为RabbitTemplate
类具有两种类似的方法:
要解决此问题,您可以像这样将第二个参数的类型强制设置为对象:
Mockito.verify(rabbitTemplate).convertAndSend(captor.capture(), (Object) captor.capture(),
Mockito.any(MessagePostProcessor.class));
或者更好的是,对于两个不同的参数,有两个不同的ArgumentCaptor
:
ArgumentCaptor<String> routingKeyCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<Object> messageCaptor = ArgumentCaptor.forClass(Object.class);
...
verify(rabbitTemplate).convertAndSend(routingKeyCaptor.capture(), messageCaptor.capture(), any(MessagePostProcessor.class));
希望这会有所帮助!
答案 1 :(得分:0)
我认为这全都取决于您真正想要测试的东西以及它所带来的商业价值。
RabbitTemplate
本身吗? Spring存储库已对此进行了测试,但是恕我直言,您不需要这样做。Service
,并且必须验证是否已发送消息?对于(1),有一些示例说明了您正在Spring Framework
here in their unit tests for the RabbitTemplate
中编写的测试类型。
例如,验证基础ConnectionFactory
实际上是created a channel:
txTemplate.execute(status -> {
template.convertAndSend("foo", "bar");
return null;
});
txTemplate.execute(status -> {
template.convertAndSend("baz", "qux");
return null;
});
verify(mockConnectionFactory, Mockito.times(1)).newConnection(any(ExecutorService.class), anyString());
// ensure we used the same channel
verify(mockConnection, times(1)).createChannel();
对于上面的(2),您不需要使用参数捕获器,等等。您可以将模拟RabbitTemplate
注入到服务中,并且我个人希望针对使用或调用方法的参数进行测试使用Mockito#any
等
FYI,在断言方面,我还要看一下AssertJ,它得到了Spring的认可,它的流畅API(尤其是intellisense)使其变得非常容易使用。
对于(3),我强烈推荐https://www.testcontainers.org/(如果您使用的是docker),但我还没有检查出来,但是可能会有一个JUnit @Rule
用于创建RabbitMQ经纪人(我必须对此进行检查)。我为ActiveMQ Artemis
做过类似的事情,它很快为您启动了代理,您可以使用排队的消息。