Spring 使用DBUnit测试JdbcDao的问题

Spring 使用DBUnit测试JdbcDao的问题,spring,oracle,exception,dbunit,unitils,Spring,Oracle,Exception,Dbunit,Unitils,我有一个AuthorJDBCDAO类和基本的CRUD方法,它扩展了AbstractJDBCDAO类并实现了AuthorDAO接口。 我通过psv main()方法测试了所有方法,一切都很好。 但现在我必须使用DBUnit测试它的方法。我的麻烦就从这里开始。 我尝试只测试create()方法,但它不能正常工作。 我正在使用Unitils、SpringDI、OracleDB来创建我的应用程序。 我将beanDataSource(dbcp2)注入beanAuthorJDBCDAO。我对注入bean使用

我有一个AuthorJDBCDAO类和基本的CRUD方法,它扩展了AbstractJDBCDAO类并实现了AuthorDAO接口。 我通过
psv main()方法测试了所有方法,一切都很好。
但现在我必须使用DBUnit测试它的方法。我的麻烦就从这里开始。
我尝试只测试
create()
方法,但它不能正常工作。 我正在使用Unitils、SpringDI、OracleDB来创建我的应用程序。 我将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");
}
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
下面是测试类执行的stacktrace

@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");
}
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。但我不明白,如果我试图从数据源获取连接,它是如何发生的,数据源是基本的CDATA源,并且支持连接池

@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;
}
下面是用于测试的简单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测试类中的事务性配置是否存在smth错误?

问题已解决。我应该通过DataSourceUtils.doReleaseConnection()关闭连接。否则,将物理关闭连接。这是我麻烦的关键。

问题解决了。我应该通过DataSourceUtils.doReleaseConnection()关闭连接。否则,将物理关闭连接。这是我麻烦的关键。

我检查了调试变量,发现在第二次尝试捕获资源时,我得到了闭合连接。我检查了调试变量,发现在第二次尝试捕获资源时,我得到了闭合连接。
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
    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());

    }