2016-12-08 2 views
0

Je suis en train d'écrire test JUnit pour ma classe de DAO et me fais erreur lorsque le test suivant dans Eclipse:test unitaire pour la classe DAO: Java Spring MVC en utilisant la base de données Hibernate et H2

package com.bookstore.dao; 
import org.junit.Assert; 
import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.test.annotation.Rollback; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  
import com.bookstore.domain.Book; 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath:**/applicationContext-test.xml"}) 
public class BookDaoImplTest { 

    private BookDao bookDao; 
    private Book book; 

    @Before 
    public void setup() { 
     book = new Book(); 
     book.setBookName("Some Book Name"); 
     book.setBookCategory("Fiction"); 
     book.setBookPrice(11.11); 
     // more properties here (not relevant for the question) 
    } 

    @Test 
    @Rollback(true) 
    public void testBookInsert() { 
     bookDao.bookInsert(book); // nullPointer happens at this line! 
     final int bookId = book.getBookId(); 
     Book insertedBook = bookDao.getBookById(bookId);  
     Assert.assertEquals(insertedBook.getBookName(), book.getBookName()); 
    } 
} 

Aussi mon DAO classe de mise en œuvre est la suivante:

package com.bookstore.dao; 
import org.hibernate.Query; 
import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Repository; 
import org.springframework.transaction.annotation.Transactional; 
import java.util.List; 
import com.bookstore.domain.Book; 
import com.bookstore.exception.BookNotFoundException; 

@Repository 
@Transactional 
public class BookDaoImpl implements BookDao { 

    @Autowired 
    private SessionFactory sessionFactory; 
    private Session session = null; 

    public List<Book> getAllBooks() { 
     session = sessionFactory.getCurrentSession(); 
     Query query = session.createQuery("FROM Book"); 
     List<Book> books = query.list(); 
     session.flush(); 
     return books; 
    } 

    public Book getBookById(int bookId) { 
     session = sessionFactory.getCurrentSession(); 
     Book bookById = (Book) session.get(Book.class, bookId); 
     session.flush(); 
     if (bookById == null) { 
      throw new BookNotFoundException(bookId); 
     } 
     return bookById; 
    } 

    public void bookInsert(Book book) { 
     session = sessionFactory.getCurrentSession(); 
     session.saveOrUpdate(book); 
     session.flush(); 
    } 

    // more methods here (not relevant for the question) 
} 

J'ai aussi créé applicationContext-test.xml dans le dossier src/test/ressources comme suit:

<?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"> 
    <bean id="dataSource" 
     class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="org.h2.Driver" /> 
     <property name="url" value="jdbc:h2:tcp://localhost/~/test" /> 
     <property name="username" value="sa" /> 
     <property name="password" value="" /> 
    </bean> 
    <bean id="sessionFactory" 
     class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.Dialect"> 
        org.hibernate.dialect.H2Dialect</prop> 
       <prop key="hibernate.hbm2ddl.auto">update</prop> 
       <prop key="hibernate.show_sql">false</prop> 
       <prop key="hibernate.format_sql">true</prop> 
      </props> 
     </property> 
     <property name="packagesToScan"> 
      <list><value>com.bookstore</value></list> 
     </property> 
    </bean> 
    <bean id="transactionManager" 
     class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactory" /> 
    </bean> 
</beans> 

Maintenant, l'erreur que je reçois dans la fenêtre de JUnit est NullPointerException à la ligne bookDao.bookInsert(book); de mon test:

JUnit window of Eclipse

Et dans la console que je peux voir ce qui suit:

INFO: HHH000232: Schema update complete 
Dec 08, 2016 10:16:41 PM org.springframework.orm.hibernate4.HibernateTransactionManager afterPropertiesSet 
INFO: Using DataSource [[email protected]9fee] of Hibernate SessionFactory for HibernateTransactionManager 
Dec 08, 2016 10:16:41 PM org.springframework.context.support.GenericApplicationContext doClose 
INFO: Closing [email protected]fcfece: startup date [Thu Dec 08 22:16:38 GMT 2016]; root of context hierarchy 
+0

faisant session une variable d'instance est une erreur, les threads peuvent accéder à la session ou de remplacer la référence à elle en même temps. –

+0

essayez d'ajouter '@' Autowired' pour bookDao' – Jerry06

+0

Nathan, voulez-vous dire que je devrais avoir 'session de session = sessionFactory.getCurrentSession()' dans chaque méthode au lieu d'une instance variable 'session privée session = null;'? – Dubliner

Répondre

0

Votre fichier applicationContext.xml ne se trouve probablement pas sur le chemin de classe de votre test unitaire. Essayez de le copier dans le dossier des ressources de votre paquet de test.

Ou vous créez déjà le dao-vous dans la méthode de configuration @Before, pourquoi vous utilisez également @Autowired?

+0

J'ai créé un autre fichier - applicationContext-test.xml sous le dossier src/test/resources et j'ai supprimé l'annotation @Autowired. On dirait que le test essaie de fonctionner, mais avec des erreurs. Quand j'ai débogué - le pointeur NULL est lancé à la ligne 'session = sessionFactory.getCurrentSession();' de ma classe BookDaoImpl. – Dubliner

+0

comment configurez-vous votre atelier de session? si son dans un fichier xml il peut également être absent de la classpath – Reek

+0

usine de session est configuré dans le fichier 'applicatioContext-test.xml' qui est situé dans le dossier' src/test/resources' – Dubliner

0

Je pense que le problème est dans la façon dont vous avez créé l'instance BookDao dans BookDaoImplTest. La seule façon pour BookDao et les beans référencés à l'intérieur d'être créés correctement est l'injection de dépendance (par exemple en utilisant @Autowired). Si vous le créez manuellement en utilisant l'opérateur "new" ou en vous moquant de lui, les champs comme "sessionFactory" peuvent être null (si vous ne les définissez pas manuellement).

+0

Si j'ajoute '@ Autowired' à 'BookDao bookDao;' J'obtiendrai l'erreur: 'SEVERE: exception interceptée tout en permettant à TestExecutionListener [org.springframewor[email protected]64616ca2] de préparer l'instance de test [[email protected]] org.springframework.beans.factory.UnsatisfiedDependencyException: Erreur lors de la création du bean avec le nom 'com.bookstore.dao.BookDaoImplTest': dépendance non satisfaite exprimée via le champ 'bookDao'; l'exception imbriquée est org.springframework.beans.factory.NoSuchBeanDefinitionException: Aucun bean qualifié n'a été trouvé ... ' – Dubliner

+0

cela signifie donc que spring ne trouve pas votre applicationContext-test.xml. Dans votre BookDaoImplTest, vous pouvez essayer de remplacer '@ContextConfiguration (emplacements = { "classpath: **/applicationContext-test.xml"})' 'avec @ContextConfiguration (emplacements = { "classpath: applicationContext-test.xml"}) ' –