2012-04-04 10 views
2

Ich habe den folgenden Testfall:Kann testen JPA + Frühling nicht

@ContextConfiguration("/spring/test-context.xml") 
@TransactionConfiguration(transactionManager="txManager") 
@Transactional() 
public class MyEntityDaoTestCase extends AbstractJUnit4SpringContextTests { 

    @Autowired 
    private MyEntityDao dao; 

    @Test 
    public void testSave_success() { 
     MyEntity e = new MyEntity(); 
     dao.save(e); 
     MyEntity result = dao.findById(e.getId()); 
     assertNotNull(result);  
    } 
} 

Meine DAO Definition hat sich wie folgt:

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:tx="http://www.springframework.org/schema/tx" 
     xsi:schemaLocation="http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
      http://www.springframework.org/schema/tx 
      http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> 

    <!-- 
     Bean post-processor for JPA annotations 
    --> 
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/> 

    <!-- 
     JPA entity manager factory 
    --> 
    <bean id="jpaEntityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"> 
     <property name="persistenceUnitName" value="unit-test-pu"/> 
    </bean> 

    <!-- 
     Transaction manager 
    --> 
    <bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
     <property name="entityManagerFactory" ref="jpaEntityManagerFactory"/> 
    </bean> 

    <!-- 
     Enable the configuration of transactional behavior based on annotations 
    --> 
    <tx:annotation-driven transaction-manager="txManager"/> 

    <!-- 
     DAO instance beans 
    --> 
    <bean id="mockEntityDao" class="mypackage.MyEntityDao"></bean> 

</beans> 

:

public abstract class MyEntityDAO { 

    @PersistenceContext 
    private EntityManager mEntityManager; 

    public void save(MyEntity entity) { 
     mEntityManager.persist(entity); 
    } 

    public MyEntity findById(Long id) { 
     return mEntityManager.find(mEntityClass, id); 
    } 
} 

My Frühlings-Config ist folgendes Ich bekomme keine Fehler während der Ausführung meines Tests, aber es wird nicht bestanden. Es sieht so aus, als ob die Methode findById() die Entität in der Datenbank nicht findet. Kann jemand beraten, wie man diesen Fall richtig prüft?

EDIT:

Mein JPA-Provider ist Hibernate. Ich verwende eine In-Memory-HSQLDB für meine Unit-Tests und haben die folgende Konfiguration:

<?xml version="1.0" encoding="UTF-8"?> 
<persistence xmlns="http://java.sun.com/xml/ns/persistence" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" 
      version="2.0"> 
    <persistence-unit name="unit-test-pu" transaction-type="RESOURCE_LOCAL"> 
     <properties> 
     <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/> 
     <property name="javax.persistence.jdbc.user" value="sa"/> 
     <property name="javax.persistence.jdbc.password" value=""/> 
     <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:."/> 
     <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/> 
     <property name="hibernate.archive.autodetection" value="class"/> 
     <property name="hibernate.show_sql" value="true"/> 
     <property name="hibernate.format_sql" value="true"/> 
     <property name="hibernate.hbm2ddl.auto" value="create"/> 
     </properties>  
    </persistence-unit> 
</persistence> 
+0

Was ist der JPA-Provider und Config hilft? – mguymon

+0

Ich verwende Hibernate. Ich habe meine Konfiguration in meinem Post hinzugefügt. –

+0

MyEntity wird korrekt beibehalten, so dass die ID für e.getId() nicht null ist? – mguymon

Antwort

0

Wenn Sie TDD strikt befolgen, sollten Sie keine In-Memory-Datenbank verwenden, sondern alles überspotten. Das Problem ist, dass die persist-Methode void zurückgibt. So können Sie nicht testen Sie die richtige Antwort (ein Unternehmen mit einer ID von einer Datenbank generiert) Eine Möglichkeit, dies zu umgehen, ist uns die Mockito doAnswer Methode, hier ein Beispiel:

@RunWith(MockitoJUnitRunner.class) 
public class CookieRepositoryTest { 

@Mock 
EntityManager em; 

@Mock 
TimeService timeService; 

@InjectMocks 
CookieRepository underTest = new CookieRepository(); 

@Test 
public void testCreateEntity() throws Exception { 
Cookie newCookie = new Cookie(); 

when(timeService.getTime()).thenReturn(new DateTime(DateTimeZone.UTC)); 

doAnswer(new Answer<Brand>() { 
@Override 
public Brand answer(InvocationOnMock invocationOnMock) throws Throwable { 
Object[] args = invocationOnMock.getArguments(); 
Cookie cookie = (Cookie) args[0]; 
cookie.setId(1); 
return null; 
} 

}).when(em).persist(any(Brand.class)); 

Cookie persistedCookie = underTest.createEntity(newCookie); 
assertNotNull(persistedCookie.getId()); 
} 

} 

Eine vollständige Erklärung gefunden werden kann auf meinem Blog post.

2

Sie könnten versuchen, @TransactionalConfiguration Annotation und die Feder JUnit runner verwenden.

So etwas wie Ihre Klasse diese zu ändern:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("/spring/test-context.xml") 
@TransactionConfiguration(transactionManager="txManager", defaultRollback=true) 
@Transactional 
public class MyEntityDaoTestCase { 

Dies auch bedeutet, dass Sie nicht den abstrakten Fall verlängern müssen (weil Sie den Frühling Läufer verwenden) - es sei denn, Sie besonders wie dieser Ansatz.

Hier mehr details

+0

Ich habe versucht, defaultRollback = true zu setzen. Es funktioniert nicht. –

+0

Nur ein Kommentar: Bitte verwenden Sie nicht defaultRollback auf True gesetzt! Hibernate behält die insert/update-Anweisungen im Speicher, bis sie in die Datenbank geleert werden (durch einen Select- oder expliziten Flush). Daher könnte Hibernate die Datenbank in Ihrem Test nie berühren, was bedeutet, dass Sie bei der Bereitstellung der Anwendung weiterhin Fehler erhalten können, obwohl Sie einen Test * hatten. – Augusto

+0

Und das ist genau mein Problem. Ich möchte überwintern, um meinen Fall zu testen. Schau dir meine Testmethode an und du wirst verstehen, was ich meine ... –

0

Wenn Sie die Persistenzschicht testen möchten, können Sie sich auch die DBUnit-Funktionen ansehen.

Sie können einen schönen Artikel von Petri Kainulainen finden hier über die Persistenz-Schicht Prüfung (in diesem Fall mit JPA) in einem Frühling-basiertes Szenario:

http://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-integration-testing/

Damit testen Sie, wenn die DAO-Klassen Verhalten wie erwartet, Schreiben und Lesen in/aus der DB, und auf der Serviceebene können Sie diesen Aspekt vermeiden, indem Sie sich mehr auf den "Schein" -Ansatz für die Geschäftslogik konzentrieren.

Hope it

Fran

Verwandte Themen