JUnit Test in Spring Context with JNDI Data Source

本文转自: http://blog.csdn.net/derek_zhang_/article/details/9067235


rigger: SpringJUnit4ClassRunner Failed to load ApplicationContext

[java]  view plain copy
  1. java.lang.IllegalStateException: Failed to load ApplicationContext  
  2.          at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99)  
  3.          at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:122)  
  4.          at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:105)  
  5.          at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:74)  
  6.          at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:312)  
  7.          at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)  
  8.          at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)  
  9.          at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)  
  10.          at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:284)  
  11.          at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)  
  12.          at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)  
  13.          at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)  
  14.          at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)  
  15.          at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)  
  16.          at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)  
  17.          at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)  
  18.          at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)  
  19.          at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)  
  20.          at org.junit.runners.ParentRunner.run(ParentRunner.java:300)  
  21.          at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)  
  22.          at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)  
  23.          at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)  
  24.          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)  
  25.          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)  
  26.          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)  
  27.          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)  
  28. Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in URL [file:/D:/eclipse_workspace/bank-api/target/classes/spring.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  
I didn't know since when my unit tests were unable to run, all tests with SpringJUnit4ClassRunner Failed to load ApplicationContext. I googled this error but didn't find a clue until I hit this post: reference 1,
Quote:  When you run your testcases, you will want to use JDBC instead of JNDI lookup. The simple reason is because you usually don't run your testcases from the application server. Thus, JNDI lookup will fail.
then I realized that JNDI configuration caused my problem and I had to pay more attention to the application context configuration if I want to perform JUnit test in spring. Unfortunately, I don't think the above post's separate application context files solution is elegant enough.

Solution Suits Me
After some homework, I find this solution fits me well:
(1) Employ the profile feature since spring framework 3.1;
(2) Base on (1), apply nested <beans/> elements;

Thereby, we don't have to split application context file into multiple files, and it's unnecessary to import resource now.

[html]  view plain copy
  1. <beans xmlns="http://www.springframework.org/schema/beans"   
  2.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  3.     xmlns:jdbc="http://www.springframework.org/schema/jdbc"   
  4.     xmlns:jee="http://www.springframework.org/schema/jee"   
  5.     xsi:schemaLocation="...">   
  6.   
  7.     <bean id="transferService" class="com.bank.service.internal.DefaultTransferService">   
  8.         <constructor-arg ref="accountRepository"/>   
  9.         <constructor-arg ref="feePolicy"/>   
  10.     </bean>   
  11.   
  12.     <bean id="accountRepository" class="com.bank.repository.internal.JdbcAccountRepository">   
  13.         <constructor-arg ref="dataSource"/>   
  14.     </bean>   
  15.   
  16.     <bean id="feePolicy" class="com.bank.service.internal.ZeroFeePolicy"/>   
  17.   
  18.     <beans profile="test">   
  19.         <bean id="dataSource"  
  20.             class="org.springframework.jdbc.datasource.DriverManagerDataSource"  
  21.             p:driverClassName="com.mysql.jdbc.Driver"   
  22.             p:url="jdbc:mysql://10.0.2.53:3306/banker"  
  23.             p:username="root" p:password="#$asd123" />   
  24.     </beans>   
  25.       
  26.     <beans profile="production">   
  27.         <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/banker" expected-type="javax.sql.DataSource" />   
  28.     </beans>   
  29. </beans>   
(3) Update web.xml
[html]  view plain copy
  1. <context-param>  
  2.         <param-name>contextConfigLocation</param-name>  
  3.         <param-value>classpath:spring.xml</param-value>  
  4.     </context-param>  
  5.     <context-param>  
  6.         <param-name>spring.profiles.active</param-name>  
  7.         <param-value>production</param-value>  
  8.     </context-param>  
  9.     <servlet>  
  10.         <servlet-name>spring</servlet-name>  
  11.         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  12.         <init-param>  
  13.             <param-name>contextConfigLocation</param-name>  
  14.             <param-value>  
  15.                 classpath:servlet-context.xml  
  16.             </param-value>  
  17.         </init-param>  
  18.     </servlet>  
(4) Use @ActiveProfiles("test") annotation in JUnit Test
[java]  view plain copy
  1. @RunWith(SpringJUnit4ClassRunner.class)  
  2. @ContextConfiguration(locations = "classpath*:spring.xml")  
  3. @ActiveProfiles("test")  
  4. public class CheckStatusTest {  
  5.     @Autowired  
  6.     private ICheckStatusService checkStatusService;  
  7.       
  8.     @Test  
  9.     public void testCheckStatus() {  
  10.         //Test Code  
  11.     }  
  12. }  
Now, the unit tests run smoothly without any ugly code or configuration!


Reference:
1. http://stackoverflow.com/questions/5197236/spring-jndi-configuration-problem
2. http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值