2015-09-04 2 views
1

J'ai une classe AuthorJDBCDAO avec des méthodes CRUD de base qui étend la classe AbstractJDBCDAO et implémente l'interface AuthorDAO. J'ai testé toutes les méthodes via psv main() method et tout allait bien. Mais maintenant je dois tester ses méthodes en utilisant DBUnit. Et ici mes problèmes commencent. J'essaie de tester seulement la méthode create() et cela ne fonctionne pas correctement. J'utilise Unitils, Spring DI, Oracle DB pour créer mon application. J'injecte le haricot DataSource(dbcp2) au haricot AuthorJDBCDAO. J'utilise la configuration XML pour les beans d'injection. Voici mon code source et mes fichiers de configuration. Classe de test.Problèmes avec les tests JdbcDao par DBUnit

@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"); 
} 

Voici stacktrace à partir de l'exécution de la classe 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 

Fragment du code de la classe AbstractJDBCDAO. Dans lequel je reçois cette exception. J'ai essayé de le déboguer et ai trouvé, que dans la deuxième connexion de bloc try-catch-with-resources est null. Mais je ne peux pas comprendre, comment cela se produit-il si j'essaie d'obtenir une connexion à partir de DataSource qui est BasicDataSource et supporte le pool de connexion.

@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; 
} 

fichiers de configuration here're pour mes haricots: 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> 

base de données test-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> 

par ressort test-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 

Et voici la classe Java simple pour les tests:

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()); 

    } 

Et il fonctionne très bien =) peut-être tort lissée avec des configurations transactionnelles dans ma DBUnit classe de test?

+0

J'ai coché des variables de débogage, et j'ai trouvé que dans la seconde try-catch-with-resources j'ai eu une connexion fermée. –

Répondre

0

Le problème est résolu. Je devrais fermer la connexion via DataSourceUtils.doReleaseConnection(). Sinon, la connexion sera fermée physiquement. C'était la clé de voûte de mes ennuis.