2012-04-04 2 views
2

У меня есть следующий тестовый случай:Не удается проверить JPA + Spring

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

Мое определение DAO имеет следующим образом:

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

Моя весна конфигурации заключается в следующем:

<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> 

Я не получаю ошибок при выполнении моего теста, но он не пройдет. Похоже, что метод findById() не найдет объект в базе данных. Может ли кто-нибудь посоветовать, как правильно проверить этот случай?

EDIT:

Мой провайдер JPA является спящий режим. Я использую в памяти HSQLDB для моих модульных тестов и имеют следующую конфигурацию:

<?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

Что провайдер JPA и конфигурации? – mguymon

+0

Я использую спящий режим. Я добавил свою конфигурацию в свой пост. –

+0

MyEntity сохранен правильно, поэтому id не равен null для e.getId()? – mguymon

ответ

0

Если вы строго придерживаетесь TDD, вы не должны использовать базу данных в памяти, но вместо этого все должно быть издевательством. Проблема в том, что метод persist возвращает void. Таким образом, вы не можете проверить правильный ответ (объект с идентификатором генерируемой базы данных) Один из способов обойти это нам метод Mockito doAnswer, вот пример:

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

} 

Полное объяснение можно найти в моем блоге post.

2

Вы можете попробовать использовать @TransactionalConfiguration аннотацию и Spring JUnit бегуна.

Что-то, как меняется ваш класс на это:

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

Это также означает, что вам не нужно, чтобы расширить абстрактный случай (потому что вы используете Spring бегуна) - если вам особенно нравится такой подход.

Вот еще details

+0

Я пробовал настройку defaultRollback = true. Это не работает. –

+0

Просто комментарий: Пожалуйста, не используйте defaultRollback для true! Hibernate сохраняет операторы вставки/обновления в памяти до тех пор, пока они не будут сброшены в БД (с помощью явного или явного флеша). Таким образом, Hibernate может никогда не касаться БД в вашем тесте, а это означает, что вы все равно можете получить ошибки при развертывании приложения *, хотя у вас был тест *. – Augusto

+0

И это моя проблема. Я ХОЧУ спящий режим, чтобы проверить мой случай. Взгляните на мой метод тестирования, и вы получите то, что я имею в виду ... –

0

Если вы хотите протестировать слой сохранения, вы также можете взглянуть на возможности DBUnit.

Вы можете найти хорошую статью от Petri Кайнулайнена здесь о тестировании уровня персистенции (в данном случае с JPA) в основе сценария Spring:

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

С этим, вы проверяете, если классы DAO вести себя так, как ожидалось, писать и читать в/из БД, а на уровне обслуживания вы можете избежать проверки этого аспекта, уделяя больше внимания «макетному» подходу для бизнес-логики.

Надеется, что это помогает

Фрэно

Смежные вопросы