Persist/commit not working in test environment with Spring JPA JUnit
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();
}
}
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, 2022Comments
-
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>