我有AuthorJDBCDAO类,它有基本的CRUD方法,它扩展了AbstractJDBCDAO类并实现了AuthorDAO接口。
我通过psv main() method
测试了所有方法,一切都很好。
但现在我必须使用DBUnit测试它的方法。在这里我的麻烦开始了。
我尝试仅测试create()
方法并且它无法正常工作。
我使用Unitils,Spring DI,Oracle DB来创建我的应用程序。
我将bean DataSource(dbcp2)
注入bean AuthorJDBCDAO
。我对注入bean使用XML配置。
这是我的源代码和配置文件。
测试课。
@SpringApplicationContext({"spring-test-config.xml"})
@DataSet(value = "AuthorDAOTest.xml", loadStrategy = CleanInsertLoadStrategy.class)
public class AuthorDAOTest extends UnitilsJUnit4 {
@SpringBean("authorJDBCDAO")
private AuthorJDBCDAO authorDAO;
@Test
public void testCreate() throws DAOException {
Author expected = new Author();
expected.setName("BLABLABLA");
expected.setExpiredDate(Timestamp.valueOf(LocalDateTime.now()));
Author result = null;
result = authorDAO.create(expected);
assertEquals(expected.getId(), result.getId());
System.out.println("Hello from test");
}
这是执行Test类的堆栈跟踪。
newsportal.exception.DAOException: java.sql.SQLException: Connection is null.
at newsportal.dao.impl.AbstractJDBCDAO.create(AbstractJDBCDAO.java:115)
at com.epam.ivanou.newsportal.dao.impl.AuthorJDBCDAOTest.testCreate(AuthorJDBCDAOTest.java:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:108)
at org.unitils.UnitilsJUnit4TestClassRunner$TestListenerInvokingMethodRoadie.runTestMethod(UnitilsJUnit4TestClassRunner.java:204)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:89)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:97)
at org.unitils.UnitilsJUnit4TestClassRunner$TestListenerInvokingMethodRoadie.runBeforesThenTestThenAfters(UnitilsJUnit4TestClassRunner.java:186)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50)
at org.unitils.UnitilsJUnit4TestClassRunner.invokeTestMethod(UnitilsJUnit4TestClassRunner.java:95)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:59)
at org.unitils.UnitilsJUnit4TestClassRunner.access$000(UnitilsJUnit4TestClassRunner.java:42)
at org.unitils.UnitilsJUnit4TestClassRunner$1.run(UnitilsJUnit4TestClassRunner.java:60)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
at org.unitils.UnitilsJUnit4TestClassRunner.run(UnitilsJUnit4TestClassRunner.java:67)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.sql.SQLException: Connection is null.
at org.apache.commons.dbcp2.DelegatingConnection.checkOpen(DelegatingConnection.java:608)
at org.apache.commons.dbcp2.DelegatingConnection.prepareStatement(DelegatingConnection.java:286)
at com.epam.ivanou.newsportal.dao.impl.AbstractJDBCDAO.create(AbstractJDBCDAO.java:106)
... 29 more
AbstractJDBCDAO类的代码片段。我得到这个例外。我试图调试它并发现,在第二个try-catch-with-resources块连接中为null。但是我无法理解,如果我尝试从DataSource获取BasicDataSource并支持连接池,它会如何发生。
@Override
public T create(T object) throws DAOException {
T persistInstance;
// Add the record
String sql = getCreateQuery();
String idName = getIdString();
String tableName = getTableName();
try (Connection connection = DataSourceUtils.getConnection(dataSource);
PreparedStatement statement = connection.prepareStatement(sql)) {
System.out.println("connection: "+ connection + " data source: " + dataSource);
prepareStatementForInsert(statement, object);
int count = statement.executeUpdate();
if (count != 1) {
throw new DAOException("On persist modify more then 1 record: " + count);
}
} catch (Exception e) {
throw new DAOException(e);
}
// Get recently inserted record
sql = getSelectQuery() + " WHERE " + idName + " = (SELECT MAX(" + idName + ") FROM "
+ tableName + ")";
try (Connection connection = DataSourceUtils.getConnection(dataSource);
PreparedStatement statement = connection.prepareStatement(sql)) //here is connection is null and SQLException is thrown {
System.out.println("connection: "+ connection + " data source: " + dataSource); //TODO connection is null in test method, but is good when using main() method
ResultSet rs = statement.executeQuery();
List<T> list = parseResultSet(rs);
if ((list == null) || (list.size() != 1)) {
throw new DAOException("Exception on findByPK new persist data.");
}
persistInstance = list.iterator().next();
} catch (Exception e) {
throw new DAOException(e);
}
return persistInstance;
}
这里是我的bean的配置文件: DAO-beans.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
<bean id="authorJDBCDAO" class="newsportal.dao.impl.AuthorJDBCDAO">
<constructor-arg ref="dataSource"/>
</bean>
数据库测试-config.xml中
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>db_test.properties</value>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxIdle" value="${jdbc.maxIdle}"/>
<property name="minIdle" value="${jdbc.minIdle}"/>
<property name="maxWaitMillis" value="${jdbc.maxWaitMillis}"/>
<property name="initialSize" value="${jdbc.initialSize}"/>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
弹簧测试-config.xml中
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="database-test-config.xml" />
<import resource="dao-beans.xml" />
</beans>
db_test.properties
jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:xe
jdbc.username=Yahor_test
jdbc.password=1234
jdbc.maxIdle=100
jdbc.minIdle=10
jdbc.maxWaitMillis=10000
jdbc.initialSize=10
这是用于测试的简单java类:
public class Test {
public static void main(String[] args) throws DAOException {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
AuthorJDBCDAO authorDAO = (AuthorJDBCDAO) ctx.getBean("authorJDBCDAO");
Author author = new Author();
author.setName("Yahor");
author = authorDAO.create(author);
System.out.println(author.getId());
}
它工作正常=) 我的DBUnit Test类中的事务配置可能有问题吗?
答案 0 :(得分:0)
问题解决了。我应该通过DataSourceUtils.doReleaseConnection()关闭连接。否则连接将在物理上关闭。这是我麻烦的基石。