Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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>
like image 879
user2023141 Avatar asked Dec 19 '22 23:12

user2023141


2 Answers

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

}
like image 148
hassan abdi Avatar answered Dec 25 '22 23:12

hassan abdi


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.

like image 38
user2023141 Avatar answered Dec 25 '22 22:12

user2023141