在利用Spring和iBatis做一個應用時,用到了數據庫連接池。在Spring配置文件中,jndi配置如下
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>jdbc/mysql</value></property>
<property name="lookupOnStartup" value="false"/>
<property name="cache" value="false"/>
<property name="resourceRef" value="true" />
<property name="proxyInterface" value="javax.sql.DataSource"/>
</bean>
但是在junit進行單元測試時,出現了問題。
org.springframework.jndi.JndiLookupFailureException: JndiObjectTargetSource failed to obtain new target object; 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
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(Unknown Source)
at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(Unknown Source)
at javax.naming.InitialContext.lookup(Unknown Source)
at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:123)
at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:85)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:121)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:146)
at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:93)
at org.springframework.jndi.JndiObjectLocator.lookup(JndiObjectLocator.java:105)
at org.springframework.jndi.JndiObjectTargetSource.getTarget(JndiObjectTargetSource.java:126)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:184)
at $Proxy0.getConnection(Unknown Source)
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:200)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:350)
at org.springframework.test.AbstractTransactionalSpringContextTests.startNewTransaction(AbstractTransactionalSpringContextTests.java:387)
at org.springframework.test.AbstractTransactionalSpringContextTests.onSetUp(AbstractTransactionalSpringContextTests.java:217)
at org.springframework.test.AbstractSingleSpringContextTests.setUp(AbstractSingleSpringContextTests.java:103)
at junit.framework.TestCase.runBare(TestCase.java:128)
at org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase.java:76)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:120)
at junit.framework.TestSuite.runTest(TestSuite.java:230)
at junit.framework.TestSuite.run(TestSuite.java:225)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
在junit環境下連接數據源失敗,爲什麼呢,因爲jndi是在tomcat下配置的,但是用junit進行單元測試的環境下是獨立於tomcat的,不能夠與jndi中的數據相連。這種問題有兩種解決辦法。
一是在進行單元測試時,利用jdbc連接數據庫。將Spring配置文件中的dataSource部分改成下面的方式:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/cms</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>admin</value>
</property>
</bean>
二是利用Spring針對單元測試而擴展的功能:
個人認爲第一種方法比較方便,只需要在進行單元測試時利用jdbc的方式,在控制層測試時,可以將其再轉換到jndi的方式上去。第二種方法通過擴展Spring的功能,相當於在java代碼中重新創建了一個dataSource,而不是通過配置文件。