Spring 无法使用JNDI数据源在JUnit中加载ApplicationContext
我在测试我的应用程序时遇到了一些问题,但它在正常执行时运行良好。 我认为它来自未找到的JNDI资源,但我不明白为什么以及如何修复它 当我启动Junit测试时,出现以下错误:Spring 无法使用JNDI数据源在JUnit中加载ApplicationContext,spring,spring-mvc,junit,jndi,spring-junit,Spring,Spring Mvc,Junit,Jndi,Spring Junit,我在测试我的应用程序时遇到了一些问题,但它在正常执行时运行良好。 我认为它来自未找到的JNDI资源,但我不明白为什么以及如何修复它 当我启动Junit测试时,出现以下错误: java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareCo
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99)
at ...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'DAOImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource com.sample.DAOImpl.myDatasource; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=myDatasource)}
Related cause: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myDatasource' defined in URL [file:src/test/resources/spring/test-dao-config.xml]: Invocation of init method failed; nested exception is 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 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
at ...
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private javax.sql.DataSource com.sample.DAOImpl.myDatasource; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=myDatasource)}
at ...
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=myDatasource)}
at ..
以下是我的配置:
Context.xml
<Resource name="jdbc/myDatasource" auth="Container" type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@database:99999:instance"
username="user"
password="password"
validationQuery="select 1 from dual"
testOnBorrow ="true"
maxActive="5"
maxIdle="1"
maxWait="-1" />
<bean id="myDatasource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/myDatasource" />
</bean>
@Repository
public class DacsDAOImpl implements DacsDAO
{
private final static Logger LOGGER = LoggerFactory.getLogger(DAOImpl.class);
@Autowired
@Qualifier("myDatasource")
private DataSource myDatasource;
....
}
还有我的测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "file:src/test/resources/spring/test-dao-config.xml" })
public class MyDAOImplTest
{
private MyDAO dao;
@BeforeClass
public static void initJndi() throws IllegalStateException, NamingException
{
//some test, but doesn't work
// SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
// builder.bind("java:comp/env/jdbc/myDatasource", "myDatasource");
// builder.activate();
}
@Before
public void setUp() throws IllegalStateException, NamingException
{
dao = new MyDAOImpl();
}
@Test
public void testTotalUser()
{
int result = dao.getTotalUser();
Assert.assertEquals(0, result);
}
}
谢谢您正在一个测试用例中运行,
Context.xml中的所有内容都不可用,因为只有tomcat上才有。为什么在测试用例中需要jndi查找?如果您想测试dao,请使用内存中的数据库,如hsql、h2或derby,并改用它。Spring有一些很好的标签,可以让您轻松使用
<jdbc:embedded-database id="myDataSource" type="H2">
// Add some init scripts here.
</jdbc:embedded-database>
最后,您的测试也有缺陷,您正在加载您的上下文,但没有使用它做任何事情。您正在@Before
方法中构造一个MyDAOImpl
。既然你什么都不做,为什么还要费心加载上下文呢 请发布堆栈跟踪的其余部分。实际上,datasource是daoImpl的一个自动连接属性。我知道有像H2这样的嵌入式数据库,我下一步将使用它,但我想在添加一些我不知道的东西之前让我的测试工作起来,这是行不通的。正如我已经提到的,您没有可用的JNDI。除非从context.xml中复制配置,否则您将无法连接到实际数据库。请配置指向实际数据库的实际数据源。然后必须使用SimpleNameingContextBuilder
将其添加到模拟JNDI树中
@BeforeClass
public static void initJndi() throws IllegalStateException, NamingException
{
//some test, but doesn't work
// Construct in-memory database
SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
builder.bind("java:comp/env/jdbc/myDatasource", myDatasource); //Actual datasource not a String!
builder.activate();
}