本文转自: http://blog.csdn.net/derek_zhang_/article/details/9067235
rigger: SpringJUnit4ClassRunner Failed to load ApplicationContext
- java.lang.IllegalStateException: Failed to load ApplicationContext
- at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99)
- at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:122)
- at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:105)
- at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:74)
- at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:312)
- at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
- at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
- at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
- at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:284)
- at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
- at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
- at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
- at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
- at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
- at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
- at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
- at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
- at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
- at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
- at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
- at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
- at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
- at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
- at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
- at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
- at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
- 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
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.
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:jdbc="http://www.springframework.org/schema/jdbc"
- xmlns:jee="http://www.springframework.org/schema/jee"
- xsi:schemaLocation="...">
- <bean id="transferService" class="com.bank.service.internal.DefaultTransferService">
- <constructor-arg ref="accountRepository"/>
- <constructor-arg ref="feePolicy"/>
- </bean>
- <bean id="accountRepository" class="com.bank.repository.internal.JdbcAccountRepository">
- <constructor-arg ref="dataSource"/>
- </bean>
- <bean id="feePolicy" class="com.bank.service.internal.ZeroFeePolicy"/>
- <beans profile="test">
- <bean id="dataSource"
- class="org.springframework.jdbc.datasource.DriverManagerDataSource"
- p:driverClassName="com.mysql.jdbc.Driver"
- p:url="jdbc:mysql://10.0.2.53:3306/banker"
- p:username="root" p:password="#$asd123" />
- </beans>
- <beans profile="production">
- <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/banker" expected-type="javax.sql.DataSource" />
- </beans>
- </beans>
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath:spring.xml</param-value>
- </context-param>
- <context-param>
- <param-name>spring.profiles.active</param-name>
- <param-value>production</param-value>
- </context-param>
- <servlet>
- <servlet-name>spring</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <init-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- classpath:servlet-context.xml
- </param-value>
- </init-param>
- </servlet>
- @RunWith(SpringJUnit4ClassRunner.class)
- @ContextConfiguration(locations = "classpath*:spring.xml")
- @ActiveProfiles("test")
- public class CheckStatusTest {
- @Autowired
- private ICheckStatusService checkStatusService;
- @Test
- public void testCheckStatus() {
- //Test Code
- }
- }
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/