Persist/commit not working in test environment with Spring JPA JUnit

10,628

Solution 1

If your test passed successfully and you do not get any exception so use @TransactionConfiguration(defaultRollback=false) per test class or use @Rollback(false) per test method. Transactional tests will rollback by default in 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());
    }

}

Solution 2

I noticed the following in the log file:

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

So, I removed

entityManager.getTransaction().commit();

from the method persistAndCommit(T) in CRUDServiceBean

This removed the exception, and there are no other exceptions anymore. The output of the test shows the following:

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

However, no record has been written in the table CURRENCY.

It's like after the test finishes, Hibernate removes the inserted record.

Solution 3

Its working for me, Ensure you initiate the transaction and commit the transaction.

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();
        }
    }
Share:
10,628
user2023141
Author by

user2023141

Excellent knowledge: Java 8, Spring (boot), SpringBatch, JPA(Hibernate), Angular, Junit, SOAP , Rest, Maven, Bitbucket, IntelliJ, Eclipse, Jenkins, Sonar JSP, Servlets, JMS, Struts, Swing, JDBC, SQL, Typescript, Oracle

Updated on June 28, 2022

Comments

  • user2023141
    user2023141 almost 2 years

    I'm trying to setup a basic JPA insert test. But nothing is saved in the DB. DB is Postgresql. Hibernate is used as Persistence provider.

    Many thanks in advance.

    @Entity
    public class Currency {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        protected Integer id;    
    
        @Column
        private String code;
    
        @Column
        private String name;
    ...
    }
    

    The CRUD class :

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

    Base class for all tests:

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

    The test class:

    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>