Java Junit/Spring/Hibernate:如何为单元测试中的Hibernate会话指定容器外数据源
我有一个applicationContext.xml,它定义了一个名为“baseDataSource”的bean 我收到这个错误:Java Junit/Spring/Hibernate:如何为单元测试中的Hibernate会话指定容器外数据源,java,spring,hibernate,spring-mvc,junit,Java,Spring,Hibernate,Spring Mvc,Junit,我有一个applicationContext.xml,它定义了一个名为“baseDataSource”的bean 我收到这个错误: 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.na
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)
我已经仔细阅读了这里的讨论
但似乎没有任何答案可以解决问题,也无法清楚地解释发生了什么。我的问题是:
如何使此数据源工作?我不能仅仅为了修改这个bean而将applicationContext.xml复制并粘贴到某个testApplicationContext.xml中。如何在我的junit测试中创建容器和autowire,而不更改此bean或复制xml配置(我的CTO会杀了我)要将自定义JNDI上下文注入单元测试,可以尝试以下操作:
@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);
}
}
这将通过InitialContext公开所需的JNDI名称
但是我建议您将baseDataSource提取到一个单独的配置文件中,然后在测试中使用一个特定的配置文件。
像这样:
在src/main/resources/applicationContext.xml中:
<import resource="datasource.jndi.xml" />
要将自定义JNDI上下文注入单元测试,可以尝试以下操作:
@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);
}
}
这将通过InitialContext公开所需的JNDI名称
但是我建议您将baseDataSource提取到一个单独的配置文件中,然后在测试中使用一个特定的配置文件。
像这样:
在src/main/resources/applicationContext.xml中:
<import resource="datasource.jndi.xml" />
我不能仅仅为了修改这个bean而将applicationContext.xml复制并粘贴到某个testApplicationContext.xml中
你不必这么做。您只需创建一个只包含数据源覆盖的配置,然后在testcase中加载这两个配置
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource>
</bean>
后者应该只包含要覆盖/替换的bean
我不能仅仅为了修改这个bean而将applicationContext.xml复制并粘贴到某个testApplicationContext.xml中
你不必这么做。您只需创建一个只包含数据源覆盖的配置,然后在testcase中加载这两个配置
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource>
</bean>
后者应该只包含要覆盖/替换的bean
然后不更改配置,不更改测试代码,不添加数据源配置,只需将安装方法添加到init remoter Server JNDI。请检查:但这如何帮助我创建sessionFactory?数据源本身是在applicationContext和
中创建的,因此,SessionFactorybean也依赖于此。运行单元测试时,您缺少JBOSS提供的JNDI容器。您需要在单元测试中伪造JNDI上下文,或者使用一个(或多个)测试上下文配置,这通常是更常见的方法。感谢Gregor,我有兴趣在选择后者之前了解前者,我如何伪造JNDI上下文?请检查:但这如何帮助我创建sessionFactory?数据源本身是在applicationContext和
中创建的,因此,SessionFactorybean也依赖于此。运行单元测试时,您缺少JBOSS提供的JNDI容器。您要么需要在单元测试中伪造JNDI上下文,要么使用一个(或多个)测试上下文配置,这通常是更常见的方法。感谢Gregor,我有兴趣在选择后者之前了解前者,我如何伪造JNDI上下文?这与我使用的解决方案非常接近。我确实创建了一个最小的独立的test-applicationContext.xml,其中包含一个看起来像
…`的数据源bean。我还需要一个sessionfactorybean代码>和事务管理器bean
,这取决于您的需要,可能是这样,也可能不是这样。如果您已经有了一个HibernateTransactionManager
,那么它可以保持原样。一般来说,如果您有一个不同的数据库,您只需要数据源
,也可能需要hibernateSessionFactory
(如果您使用JTA,但在测试中不使用,则需要事务管理器)。这与我使用的解决方案非常接近。我确实创建了一个最小的独立的test-applicationContext.xml,其中包含一个看起来像
…`的数据源bean。我还需要一个sessionfactorybean代码>和事务管理器bea
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:WEB-INF/applicationContext.xml", "applicationContext-test.xml"})