Reputation: 19260
I'm using Java 8, JUnit 4.12, Spring 4, and Hibernate 5.2.12.Final. I want to test a Hibernate method where I update some rows. The method looks like this
final CriteriaBuilder qb = m_entityManager.getCriteriaBuilder();
final CriteriaUpdate<FailedEvent> q = qb.createCriteriaUpdate(FailedEvent.class);
final Root<FailedEvent> root = q.from(FailedEvent.class);
q.where(qb.and( qb.equal(root.get(FailedEvent_.objectId), objectId) ));
q.set(root.get(FailedEvent_.flaggedForDelete), true);
affectedRows = m_entityManager.createQuery(q).executeUpdate();
return affectedRows > 0;
I have the following JUnit test to verify this
public class FailedEventDaoTest extends AbstractTransactionalJUnit4SpringContextTests
...
@Test
public final void testFlagForDeleteByObjectId()
{
final String eventId = "testId";
final FailedEvent event = failedEventDao.findByEventId(eventId);
Assert.assertFalse("A pre-condition fo this test is that an failed_event record with id \"" + eventId + "\" have a non-empty object id.", StringUtils.isEmpty(event.getObjectId()));
Assert.assertTrue(failedEventDao.flagForDeleteByObjectId(event.getObjectId()));
final FailedEvent foundEvent = failedEventDao.findByEventId(eventId);
Assert.assertTrue("Failed to mark flag for deletion.", foundEvent.getFlaggedForDelete());
} // testFlagForDeleteByObjectId
But my test fails on the last line,
Assert.assertTrue("Failed to mark flag for deletion.", foundEvent.getFlaggedForDelete());
Is this because the transaction hasn't completed yet so nothing has been updated in the database? What's the way I can validate that the right records are updated?
Upvotes: 9
Views: 1822
Reputation: 1292
You should consider not to extend the abstract class and use a different approach. For example
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
on the class.
Like:
package com.example;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import com.example.model.Person;
import com.example.service.PersonService;
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
@ContextConfiguration("classpath:/spring-beans.xml")
public class PersonServiceIntegrationTests {
@Autowired
private PersonService personService;
@Autowired
private JdbcTemplate jdbcTemplate;
@Test
public void shouldCreateNewPerson() {
Person person = new Person();
person.setFirstName("Kenan");
person.setLastName("Sevindik");
long countBeforeInsert = jdbcTemplate.queryForObject("select count(*) from t_person", Long.class);
Assert.assertEquals(2, countBeforeInsert);
personService.create(person);
long countAfterInsert = jdbcTemplate.queryForObject("select count(*) from t_person", Long.class);
Assert.assertEquals(3, countAfterInsert);
}
@Test
public void shouldDeleteNewPerson() {
long countBeforeDelete = jdbcTemplate.queryForObject("select count(*) from t_person", Long.class);
Assert.assertEquals(2, countBeforeDelete);
personService.delete(1L);
long countAfterDelete = jdbcTemplate.queryForObject("select count(*) from t_person", Long.class);
Assert.assertEquals(1, countAfterDelete);
}
@Test
public void shouldFindPersonsById() {
Person person = personService.findById(1L);
Assert.assertNotNull(person);
Assert.assertEquals("John", person.getFirstName());
Assert.assertEquals("Doe", person.getLastName());
}
}
Check this out https://examples.javacodegeeks.com/enterprise-java/spring/write-transactional-unit-tests-spring/#section_7
Or
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
classes = { StudentJpaConfig.class },
loader = AnnotationConfigContextLoader.class)
@Transactional
public class InMemoryDBTest {
@Resource
private StudentRepository studentRepository;
@Test
public void givenStudent_whenSave_thenGetOk() {
Student student = new Student(1, "john");
studentRepository.save(student);
Student student2 = studentRepository.findOne(1);
assertEquals("john", student2.getName());
}
}
Check this out https://www.baeldung.com/spring-jpa-test-in-memory-database
Upvotes: 3
Reputation: 1292
Try @AfterTransaction Annotation to test the result.
@AfterTransaction
public final void theRealTest()
{
Assert.assertTrue("Failed to mark flag for deletion.", foundEvent.getFlaggedForDelete());
}
https://www.springbyexample.org/examples/simple-spring-transactional-junit4-test-code-example.html
if this is also not working try:
"So, you need to create multiple transactions inside your test method. As you can see, you cannot use AbstractTransactionalJUnit4SpringContextTests, because it creates a single transaction for the whole test method, and cannot use bare AbstractJUnit4SpringContextTests, because it creates no transactions at all.
The solution is to use AbstractJUnit4SpringContextTests and manage transactions inside your test method programmatically.
You need to inject PlatformTransactionManager into your test, create TransactionTemplate from it and use it to demarcate your transactions as described in 11.6 Programmatic transaction management."
found here: Using AbstractTransactionalJUnit4SpringContextTests with commit halfway through
Upvotes: 4