10

I've build a Spring application that receives JMS messages (@JmsListener). During development I'd like to send some messages to the JMS-queue the listener listens to, so I wrote a unit-test that sends some messages (JmsTemplate). In this unit-test I use @SpringBootTest and @RunWith(SpringRunner.class) in order to load the application context (beans for datasources etc).

However, when the unit-test starts, it also loads the jms listener bean which directly starts consuming my new messages.

I would like to disable this jms listener bean in this test scenario so that messages are just added to the queue. Then later, I can start the main application and watch them being consumed.

How should I approach this?

I guess I could also have asked how I could disable a bean in general.

Thanks in advance.

Andrii Abramov
  • 10,019
  • 9
  • 74
  • 96
codesmith
  • 1,381
  • 3
  • 20
  • 42

4 Answers4

8

You could use profiles to solve this problem.

To your listener, add the @Profile annotation:

@Profile("!test-without-jmslistener")
public class JmsListenerBean {
    ...
}

This tells Spring that it should only create an instance of this bean if the profile "test-without-jmslistener" is not active (the exclamation mark negates the condition).

On your unit test class, you add the following annotation:

@ActiveProfiles("test-without-jmslistener)
public class MyTest {
    ...
}

Now the Spring test runner will activate this profile before running your tests, and Spring won't load your bean.

Rolf Schäuble
  • 690
  • 4
  • 15
2

Instead of using profiles you can also achieve this with a property:

@ConditionalOnProperty(name = "jms.enabled", matchIfMissing = true)
public class JmsListenerBean {
    ...
}

The matchIfMissing attribute tells Spring to set this property to true by default. In your test class you can now disable the JmsListenerBean:

@TestPropertySource(properties = "jms.enabled=false")
public class MyTest {
    ...
}
kurt
  • 21
  • 1
1

Another solution to this problem: add @ComponentScan() to the test class to skip the loading of the specified beans.

@SpringBootTest
@RunWith(SpringRunner.class)
@ComponentScan(basePackages="com.pechen.demo", excludeFilters=@Filter(type=FilterType.ASSIGNABLE_TYPE, classes=JmsListener.class))
public class MyTest(){

}

Any more please refer to spring component scan include and exclude filters.

Dave Pateral
  • 1,415
  • 1
  • 14
  • 21
0

I think you can do it by this code:-

private void stopJMSListener() {
    if (customRegistry == null) {
        customRegistry = context.getBean(JmsListenerEndpointRegistry.class);
    }
    customRegistry.stop();
}

private void startJMSListener() {
    if (customRegistry == null) {
        customRegistry = context.getBean(JmsListenerEndpointRegistry.class);
    }
    customRegistry.start();
}
Azhy
  • 704
  • 3
  • 16
Prabin
  • 29
  • 2