I've written a Spring Boot Test, that writes into a JMS queue and is expecting some processing via an JMS listener. In the listener, I'm trying to read an object from S3. The AmazonS3 class should be replaced by a MockBean. In my test I set up the mock like this:
@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
}
}
But the issue is that when running multiple Spring Boot tests , the MyJmsListener class contains a mock that is different from the one created in the Test. It's a mock, but for example the getObjectContent() returns null. But when I run the test alone, everything works fine.
I've tried to inject the AmazonS3 bean into the MyJmsPublisher and call the mocked method there and it worked. So I suspect, that it's because the JMS listener operates in a different thread.
I've found this thread and also set the reset to all available options, but does not make any difference. I also tried this OP's approach that worked for them, where I create a mock via the @Bean annotation like this:
@Configuration
public class MyConfig {
@Bean
@Primary
public AmazonS3 amazonS3() {
return Mockito.mock(AmazonS3.class);
}
}
But this just has the same behavior as mentioned above.
So can you actually use the @MockBean annotation when using different Threads like using a @JMSListener? Or am I missing something?
