我编写了一个 Spring Boot 测试,该测试写入 JMS 队列并期望通过 JMS 监听器进行一些处理。在监听器中,我尝试从 S3 读取一个对象。 AmazonS3
类应替换为 MockBean。在我的测试中,我像这样设置了模拟:
@SpringBootTest
public class MyTest {
@Autowired
MyJmsPublisher jmsPlublisher;
@MockBean
AmazonS3 amazonS3;
@Test
public void test() {
final S3Object s3Object = mock(S3Object.class);
when(s3Object.getObjectContent()).thenReturn(mock(S3ObjectInputStream.class));
when(amazonS3.getObject(anyString(), anyString())).thenReturn(s3Object);
jmsPlublisher.publishMessage("mymessage");
Awaitility.await().untilAsserted(() -> {
//wait for something here
});
}
}
@Component
@RequiredArgsConstructor
public class MyJmsPublisher {
private final JmsTemplate jmsTemplate;
public void publishMessage(String message) {
jmsTemplate.convertAndSend("destination", message);
}
}
@Component
@RequiredArgsConstructor
public class MyJmsListener {
private final AmazonS3 amazonS3;
@JmsListener(destination = "destination")
public void onMessageReceived(String message) {
final S3ObjectInputStream objectContent = amazonS3.getObject("a", "b").getObjectContent();
// some logic here
}
}
但问题是,当运行多个 Spring Boot 测试时,MyJmsListener
类包含一个与测试中创建的模拟不同的模拟。这是一个模拟,但例如 getObjectContent()
返回 null。 但是当我单独运行测试时,一切正常。
我尝试将 AmazonS3
bean 注入(inject) MyJmsPublisher
并在那里调用模拟方法,并且成功了。所以我怀疑,这是因为 JMS 监听器在不同的线程中运行。
我找到了this thread并将 reset
设置为所有可用选项,但没有任何区别。我还尝试了这个对他们有用的OP方法,我通过 @Bean 注释创建了一个模拟,如下所示:
@Configuration
public class MyConfig {
@Bean
@Primary
public AmazonS3 amazonS3() {
return Mockito.mock(AmazonS3.class);
}
}
但这与上面提到的行为相同。
那么,当使用不同的线程(例如使用@JMSListener
)时,您实际上可以使用@MockBean
注释吗?或者我错过了什么?
最佳答案
带有@JmsListener注释方法的Spring Bean在被辅助线程激活时会注入(inject)从先前测试执行中泄漏的bean。实际的解决方法是将测试执行器配置为对每个类使用独立的虚拟机,以避免此问题。
对于 Maven 执行,您可以通过设置 reuseForks
选项来配置 maven-failsafe-plugin
或 maven-surefire-plugin
。例如:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<reuseForks>false</reuseForks>
</configuration>
</plugin>
您还可以在 JUnit IDE 工具中轻松将Fork 模式
更改为Class
,以执行多个测试。 IntelliJ 示例:
使用@DirtiesContext
不起作用,不幸的是,我仍然找不到这个问题的根本原因 - 我的预感是这可能与使用内存中的实例有关ActiveMQ 代理,位于执行共享的 VM 实例中。
关于java - 运行多个 Spring Boot 测试时,@MockBean 在 JMS 监听器中使用不同的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68080623/