我是Mockito的新手,我面临着一个关于顽固的论点不匹配的问题。
到目前为止,我认为这会很好,因为在我的实现中,jmsTemplate是jmsTemplateService的一个缺陷,所有东西都是通过@Mock和@InjectMocks注入的。
理论上,我是在模拟调用的依赖方法的执行
convertAndSend(String destinationName, final Object message, final MessagePostProcessor postProcessor)试验的主要部分
Message message = Mockito.mock(Message.class);
MessagePostProcessor messagePostProcessor = (x) -> message;
doNothing()
.when(jmsTemplate)
.convertAndSend(queue, obj, messagePostProcessor);
jmsTemplateService.sendMessage(queue, obj);但是mockito抛出了一个顽固的论点错配错误,这实际上让我明白我没有正确地坚持。
- this invocation of 'convertAndSend' method:
jmsTemplate.convertAndSend(
"queueA",
Obj(),
com.example.JmsTemplateService$$Lambda$383/0x0000000800dd9440@5fb7183b
);
-> at com.example.JmsTemplateService.sendMessage(JmsTemplateService.java:64)
- has following stubbing(s) with different arguments:
1. jmsTemplate.convertAndSend(
"queueA",
Obj(),
com.example.JmsTemplateServiceTest$$Lambda$382/0x0000000800ddb360@74ad8d05
);最后一个参数似乎是实际的问题,但我不知道如何在不模拟jmsTemplate依赖项的情况下捕获它。
这是JmsTemplateService.sendMessage的当前实现(字符串队列,obj)
public void sendMessage(String queue, Object obj) {
try {
jmsTemplate.convertAndSend(queue, obj, message -> {
//do stuffs before sending the message
});
}catch (Exception e) {
//handle exception
}对于模拟convertAndSend方法可能有什么问题,有什么暗示吗?
非常感谢您的帮助!
发布于 2022-04-02 21:23:12
似乎是最后一个参数是实际问题,但我不知道如何在不模拟jmsTemplate依赖项的情况下捕获它。
实际上,您是在模拟jmsTemplate,否则它会抛出一个异常,因为jmsTemplate变量不是一个模拟。
doNothing()
.when(jmsTemplate) <- a mock is expected to be used here
.convertAndSend(queue, obj, messagePostProcessor);您是对的,因为使用的是不同的实例,所以最后一个参数是实际问题。
第一个实例由lambda在测试中定义:
MessagePostProcessor messagePostProcessor = (x) -> message;第二个是在执行对jmsTemplate.convertAndSend(..., ..., message -> {...})的调用时用其他lambda定义的。
显然,您得到了该错误,因为您正在验证jmsTemplate.convertAndSend(...)是用您在测试中定义的参数调用的。类似于:
verify(jmsTemplate).convertAndSend(queue, obj, messagePostProcessor);您可以做的是将any()作为验证中的第三个参数,并期望类似于ArgumentsMatchers.eq(queue)和ArgumentsMatchers.eq(obj)的参数作为其他参数:
verify(jmsTemplate).convertAndSend(ArgumentsMatchers.eq(queue), ArgumentsMatchers.eq(obj), any());Update:测试MessagePostProcessor内部依赖项的可能解决方案
class JmsTemplateServiceTest {
@Mock
private JmsTemplate jmsTemplate;
@Mock
private Message message;
@Captor
private ArgumentCaptor<String> queueCaptor;
@Captor
private ArgumentCaptor<String> messageCaptor;
@Captor
private ArgumentCaptor<MessagePostProcessor> messagePostProcessorArgumentCaptor;
@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
void testJmsTemplateWorksWithCorrectMessagePostProcessor() throws JMSException {
// Given
String destinationQueue = "test-queue";
String testMessage = "test message";
// When
doNothing().when(jmsTemplate).convertAndSend(destinationQueue, testMessage, message -> message);
// Inline dummy implementation that adds an element to a list defined in this test scope
List<String> stateCustomDependency = new ArrayList<>();
CustomDependency customDependency = () -> stateCustomDependency.add("Got executed!");
// Performs service call
JmsTemplateService jmsTemplateService = new JmsTemplateService(jmsTemplate, customDependency);
jmsTemplateService.sendMessage(destinationQueue, testMessage);
// Then verify the service actually invokes the jmsTemplate and capture the arguments passed to it
verify(jmsTemplate).convertAndSend(queueCaptor.capture(), messageCaptor.capture(), messagePostProcessorArgumentCaptor.capture());
// Verify values of queue and message
assertEquals(destinationQueue, queueCaptor.getValue());
assertEquals(testMessage, messageCaptor.getValue());
// Verify the MessagePostProcessor instantiated inside the service invokes the lambda dependencies
MessagePostProcessor messagePostProcessorToVerify = messagePostProcessorArgumentCaptor.getValue();
messagePostProcessorToVerify.postProcessMessage(message);
assertEquals(1, stateCustomDependency.size()); // Ensure the CustomDependency was invoked
assertEquals("Got executed!", stateCustomDependency.get(0)); // Ensure the right String was added by CustomDependency
}
}如果您还需要对Message对象调用某些方法,则必须添加类似于when(message.someMethod(...)).thenReturn(...)的语句。
希望能帮上忙!
发布于 2022-04-02 21:17:35
这是因为用于存根的MessagePostProcessor与执行测试方法时传递给JmsTemplate的实际实例不同。
传递给模拟的MessagePostProcessor是一个新实例,它是在测试方法内部创建的,而用于阻塞的实例则是在测试方法之外创建的。它们显然是两个不同的例子。
因为convertAndSend()在JmsTemplate中返回了void,所以没有什么需要存根的。在执行测试方法之后,您可以简单地用预期的参数验证它是否被正确执行。类似的事情:
@ExtendWith(MockitoExtension.class)
public class JmsTemplateServiceTest {
@Mock
private JmsTemplate jmsTemplate;
private JmsTemplateService jmsTemplateService;
@BeforeEach
public void init() {
jmsTemplateService = new JmsTemplateService(jmsTemplate);
}
@Test
public void convertAndSendTest() {
Object someObject = ....;
jmsTemplateService.sendMessage("queueA", someObject);
verify(jmsTemplate).convertAndSend(eq("queueA"), eq(someObject), any());
}
}https://stackoverflow.com/questions/71720593
复制相似问题