user3412098
user3412098

Reputation: 57

Prevent Spring from instantiating certain beans during unit tests

The production applicationContext.xml defines several beans, seen below (mostly JMS resources) that are only relevant while deployed in production. The unit tests have mock implementations that completely bypass any JMS.

<jee:jndi-lookup id="jmsConnectionFactory" jndi-name="java:/JmsXA" resource-ref="false" proxy-interface="javax.jms.ConnectionFactory"/>
<jee:jndi-lookup id="myQueue" jndi-name="java:jboss/exported/jms/queue/myQueue"/>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>
<bean id="myMessageHandler" class="com.example.MyMessageHandler" />
<bean id="jndiDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver"/>

With the above in the main applicationContext.xml, I get the following exception during the tests since there is no JNDI container available.

javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
    at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:662)
    at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:307)
    at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:344)
    at javax.naming.InitialContext.lookup(InitialContext.java:411)
    at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:154)
    at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87)
    at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152)
    at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:178)
    at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:95)
    at org.springframework.jndi.support.SimpleJndiBeanFactory.getBean(SimpleJndiBeanFactory.java:113)

Is it possible to tell Spring not to attempt to load those beans (whose ids I know) in the test applicationContext.xml? Or have a "null bean" since I know they will never be used? This would be less work than mocking them like in How to test a mocked JNDI datasource with Spring? .

Upvotes: 2

Views: 3185

Answers (1)

John B
John B

Reputation: 32949

What I suggest in general is the following. Break up your context files into multiple files. Generally isolate the beans that should not be used during testing in a separate context file. Have a single context file that imports all the bean definition files.

For your test, only load the files with the beans that you need for the test. If you have a bean A that you need for the test and depends on bean B, use Springockito's @ReplaceWithMock to mock B and inject it into the context.

In your case I would suggest moving your jndi-lookup beans into a separate context and mocking / replacing jmsConnectionFactory or jmsTemplate (I would lean towards replacing jmsTemplate).

Upvotes: 2

Related Questions