I have a spring boot application that does not much more than listening to an SQS queue via a component "MessageHandler" that has a @SqsListener-annotated method, and start some work when a message arrives.
There is also a boot-starter-web dependency, since we want to fetch health status and metrics via http in production.
Now I wanted to write a module test, that already has an application context and autowires beans. I also found out how to disable the web server that is not needed by the test:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = NONE)
However, the MessageHandler bean also gets instantiated and tries to connect to AWS, which I'd like to prevent.
One solution that works is to have a test implementation in src/test/java with @Primary annotation, whose handleMessage method does NOT have the @SqsListener annotation:
@Component
@Primary
public class TestMessageHandler implements MessageHandler {
@Override
public void handleMessage(final NewMessage newMessage) throws Exception {
return null;
}
}
But now I'd like to also test the (real) MessageHandler bean, meaning, I'd like Spring to instantiate it and autowire it's dependencies, but I still don't want the @SqsListener annotations to become active, so I can invoke it like this in my test:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = NONE)
public class IntegrationTest {
@Autowired
private RealMessageHandler messageHandler;
@Test
public void testHandleMessage() throws Exception {
messageHandler.handleMessage(new NewMessage(...));
}
}
So what I need is to switch off the magic from the spring-cloud-aws-starter module that sets up the SQS listener for the handleMessage method in the RealMessageHandler.
Any clue how I would do that?
I had a similar issue and resolved it by mocking the SimpleMessageListenerContainer bean. I plan to do this for multiple integration tests so to those tests more readable I've created a @TestConfiguration class which I then import in the test.
This is my configuration class:
/**
* Configuration class for integration test that do not need message listening capabilities.
*/
@TestConfiguration
public class MockMessageListenerConfiguration {
@MockBean
private SimpleMessageListenerContainer messageListenerContainer;
}
And I use it like this:
@SpringBootTest
@Import({MockMessageListenerConfiguration.class})
class BookingRepositoryIT {...}
After this, the connection refused warnings related to AWS SQS disappeared.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With