使用Spring JPA JUnit保持/提交不在测试环境中工作

时间:2015-10-03 11:43:31

标签: java spring hibernate jpa junit

我正在尝试设置基本的JPA插入测试。但是DB中没有保存任何东西。 DB是Postgresql。 Hibernate用作持久性提供程序。

非常感谢提前。

@Entity
public class Currency {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    protected Integer id;    

    @Column
    private String code;

    @Column
    private String name;
...
}

CRUD课程:

@Repository
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@Transactional(propagation = Propagation.REQUIRED)
public class CRUDServiceBean implements CRUDService {

      @PersistenceContext(type = PersistenceContextType.EXTENDED)
      private EntityManager entityManager;

       public EntityManager getEntityManager() {
            return entityManager;
        }

        public <T extends BaseEntity> T persistAndCommit(T t) {
            entityManager.persist(t);
            entityManager.refresh(t);
            entityManager.getTransaction().commit();
            return t;
        }

        ...
        ...
}

所有测试的基类:

@RunWith(SpringJUnit4ClassRunner.class)
@Configurable(autowire = Autowire.BY_NAME)
@ContextConfiguration(locations = { "classpath:context-test.xml" })
public class BaseTest {
}

测试类:

public class CurrencyCreateTest extends BaseTest {

    @Autowired
    CRUDService crudService;

    @Test
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void createCurrency() throws Exception {
        Currency currency = new Currency();
        currency.setCode("EUR");
        currency.setName("Euro");
        currency = crudService.persistAndCommit(currency);
    }
}

context-test.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"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
           http://www.springframework.org/schema/tx 
           http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
           http://www.springframework.org/schema/context 
           http://www.springframework.org/schema/context/spring-context-4.0.xsd">         

    <context:component-scan base-package="com.chartinvest"/>

    <bean id="contextApplicationContextProvider" class="com.chartinvest.util.ApplicationContextProvider"></bean> 


    <!-- the parent application context definition for the springapp application -->

    <!-- dataSource -->
    <bean id="dataSourceFinance" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName"><value>org.postgresql.Driver</value></property>
      <property name="url"><value>jdbc:postgresql://localhost/db_finance_test</value></property>
      <property name="username"><value>postgres</value></property>
      <property name="password"><value>xxxxxxxx</value></property>
    </bean> 

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />       
    </bean>  

    <bean id="entityManagerFactory"
          class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="mypersistenceunit" />
        <property name="dataSource" ref="dataSourceFinance" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true" />
                <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
            </bean>
        </property>
        <property name="jpaPropertyMap">
            <map>
                <entry key="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
            </map>
        </property>
    </bean>

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

</beans>

4 个答案:

答案 0 :(得分:7)

如果你的测试成功通过并且你没有得到任何异常,那么每个测试类使用 @TransactionConfiguration(defaultRollback = false)或者每个测试使用 @Rollback(false)方法。 默认情况下,事务测试将在spring test context中回滚。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={
  "test-context.xml"})
@TransactionConfiguration(defaultRollback=false)
@Transactional
public class SampleCrudTest {

    @Autowired
    private SampleCrud sampleCrud;

    @Before 
    public void onSetUpInTransaction() throws Exception {
        //Populate Test Data
    }


    @Test
    public void registerSample() {

        Sample sample = new Sample("foo");
        sampleCrud.save(sample);
        assertNotNull(sample.getId());
    }

}

答案 1 :(得分:1)

我在日志文件中注意到以下内容:

java.lang.IllegalStateException: Cannot execute getTransaction() on a container-managed EntityManager
    at 
...
...

所以,我删除了

  

entityManager.getTransaction()提交();

来自CRUDServiceBean中的方法persistAndCommit(T)

这删除了异常,并且不再有其他例外。 测试结果显示如下:

Hibernate: insert into Currency (code, name) values (?, ?)

但是,CURRENCY表中没有记录任何记录。

在测试完成后,Hibernate会删除插入的记录。

答案 2 :(得分:1)

它为我工作,请确保您启动事务并提交事务。

public Transaction startTransaction(Session session) throws HibernateException {
        return session.beginTransaction();
    }

...... your test code goes here......

public void endTransaction(Session session) throws HibernateException {

        if (session != null) {
            session.getTransaction().commit();
        }
    }

答案 3 :(得分:0)

您可以使用@Rollback(false)注释测试(或测试基类)

例如:

@DataJpaTest
@RunWith(SpringRunner.class)
@Rollback(false)
abstract class RepositoryTest {
  ...
}

class UserReportitoryTest extends RepositoryTest {

    @Autowired
    UserRepository repository;

   @Test
   void it_should_save_the_user() {
     repository.save(user);
   }
}