Reputation: 8654
I have an applicationContext.xml which defines a bean called "baseDataSource"
<bean id="baseDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="resourceRef" value="true"/>
<property name="jndiName" value="java:/MySQLDS20"/>
</bean>
Now ordinarily this is created fine within a jboss application using Spring and Hibernate. But when I try to instantiate this IOC container as part of unit testing via
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:WEB-INF/applicationContext.xml"})
I recieve this error:
Caused by: 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.JndiObjectLocator.lookup(JndiObjectLocator.java:105)
at org.springframework.jndi.JndiObjectFactoryBean.lookupWithFallback(JndiObjectFactoryBean.java:201)
at org.springframework.jndi.JndiObjectFactoryBean.afterPropertiesSet(JndiObjectFactoryBean.java:187)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
I have thoroughly read the discussion here
But no answer there seems to either solve the issue or clearly explain what is going on. My question is this:
How do I maker this datasource work? I cannot copy and paste my applicationContext.xml into some testApplicationContext.xml just for the purpose of modifying this one single bean. What can I do to create the container and autowire in my junit tests without changing this bean or duplicating the xml config (my CTO will shoot me)
Upvotes: 2
Views: 3811
Reputation: 359
But David Williams need no copy *.xml, the purpose is very clearly, no change of configration, no change of source code, just test with JNDI.
below is my method: 1. search JNDI env in your remote Server. 2. with setup() method to init your Server JNDI properties.
then no change of configration, no change no test code, no addition datasource config, just add setup method to init remoter Server JNDI.
Upvotes: 0
Reputation: 124441
I cannot copy and paste my applicationContext.xml into some testApplicationContext.xml just for the purpose of modifying this one single bean.
You don't have to. You only have to create a configuration containing only an override for the datasource, then load both in your testcase.
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource>
</bean>
Then in your test case load this together with your actual file and the bean definition will override the one in your actual configuration.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:WEB-INF/applicationContext.xml", "applicationContext-test.xml"})
The latter should only contain beans you want to override/replace.
Upvotes: 2
Reputation: 2305
To inject a custom JNDI context into your unit test you could try the following:
@BeforeClass
public static void setUp() {
DataSource ds = null; // Construct data source manually
ds.setURL("..."); ds.setUser("..."); ds.setPassword("...");
SimpleNamingContextBuilder builder = null;
try {
builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
builder.bind("java:java:/MySQLDS20",ds);
} catch (NamingException e) {
logger.error(e);
}
}
This will expose the required JNDI name through the InitialContext.
But I would recommend you to extract the baseDataSource into a separate configuration file and then use a specific configuration file for your tests instead. Like this:
In src/main/resources/applicationContext.xml:
<import resource="datasource.jndi.xml" />
JUnit Test Class:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({
"classpath*:/datasource.test.xml",
})
public class MyTests
{
...
}
Upvotes: 2