question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Expected database doesn't work with transactional and delete

See original GitHub issue

When using @Transactional, TransactionDbUnitTestExecutionListener.class and @ExpectedDatabase, updating a row makes the expected database to always fail.

Here is a exemple :

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = MvcUnitTestConfiguration.class)
@DatabaseSetup("uuidtest.xml")
@DatabaseTearDown(value = "uuidtest.xml", type = DatabaseOperation.DELETE)
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
        DirtiesContextTestExecutionListener.class,
        TransactionDbUnitTestExecutionListener.class })
@Transactional
@TransactionConfiguration(defaultRollback = true)
public class TestDUITransactional {

@Autowired
private WebApplicationContext   wac;
@Autowired
TempUuidDaoI tempUuidDaoI;

private MockMvc mockMvc;

@Before
public void setup() {
    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}

@Test
@ExpectedDatabase(value = "testDelete.xml", assertionMode = DatabaseAssertionMode.NON_STRICT_UNORDERED)
public void testDeleteUuid() throws Exception {
    Integer nb = tempUuidDaoI.getAll().size();
    tempUuidDaoI.delete(tempUuidDaoI.get(1));
    assertEquals(nb-1, tempUuidDaoI.getAll().size());
}

@Test
@ExpectedDatabase(value = "testUpdate.xml", assertionMode = DatabaseAssertionMode.NON_STRICT_UNORDERED)
public void testUpdateUuid() throws Exception {
    TempUuid tu = tempUuidDaoI.get(1);
    tu.setUuid("4b2f02ca-d857-4c95-b7fa-ee6283ce0d66");
    tempUuidDaoI.update(tu);
    tu = tempUuidDaoI.get(1);
    assertEquals("4b2f02ca-d857-4c95-b7fa-ee6283ce0d66", tu.getUuid());
}

@Test
@ExpectedDatabase(value = "testInsert.xml", assertionMode = DatabaseAssertionMode.NON_STRICT_UNORDERED)
public void testInsertUuid() throws Exception {
    Integer nb = tempUuidDaoI.getAll().size();
    TempUuid tu = new TempUuid();
    tu.setUuid("4b2f02ca-d857-4c95-b7fa-ee6283ce0d67");
    tempUuidDaoI.insert(tu);
    assertEquals(nb+1, tempUuidDaoI.getAll().size());
}

}

In this code, only the update doesn’t work.

The original db :

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <PDI.TEMP_UUIDS tuu_id="1" uuid="4b2f02ca-d857-4c95-b7fa-ee6283ce0d64" />
    <PDI.TEMP_UUIDS tuu_id="2" uuid="4b2f02ca-d857-4c95-b7fa-ee6283ce0d65" />
</dataset>

testDelete.xml :

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <PDI.TEMP_UUIDS tuu_id="2" uuid="4b2f02ca-d857-4c95-b7fa-ee6283ce0d65" />
</dataset>

testUpdate.xml :

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <PDI.TEMP_UUIDS tuu_id="1" uuid="4b2f02ca-d857-4c95-b7fa-ee6283ce0d66" />
    <PDI.TEMP_UUIDS tuu_id="2" uuid="4b2f02ca-d857-4c95-b7fa-ee6283ce0d65" />
</dataset>

testInsert.xml :

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <PDI.TEMP_UUIDS tuu_id="1" uuid="4b2f02ca-d857-4c95-b7fa-ee6283ce0d64" />
    <PDI.TEMP_UUIDS tuu_id="2" uuid="4b2f02ca-d857-4c95-b7fa-ee6283ce0d65" />
    <PDI.TEMP_UUIDS tuu_id="3" uuid="4b2f02ca-d857-4c95-b7fa-ee6283ce0d67" />
</dataset>

I’ve checked that the methods to update/delete/insert work, as does the dao. I use postgresql for anything else than unit testing for the project. I use hibernate H2 for testing.

Any idea on where does this come from ?

Issue Analytics

  • State:closed
  • Created 9 years ago
  • Comments:6

github_iconTop GitHub Comments

2reactions
ekravchenkocommented, Mar 28, 2015

Hi nyddogghr,

The issue that you described is very interesting. I created a sample application that shows this problem: https://github.com/ekravchenko/testingzone/tree/master/spring-dbunit-issue75

In the sample application I’m using same entity and dataset files that you provided in the example. Instead of DAO I’m using spring-data-jpa CrudRepository but that shouldn’t matter cause I could reproduce the issue you described.

If I understand you right testInsert and testDelete work but testUpdate fails. The root of the problem is the @Transactional annotation which causes the tests to be wrapped in the transaction. DBUnit checks the expected dataset however data is not inserted/updated cause it only happens at the end of transaction. If this statement is correct then none of your tests should work.

The reasonable questions is ‘why testInsert and testDelete work then’? They work because you have the following line in tests:

assertEquals(nb-1, tempUuidDaoI.getAll().size());

If you don’t configure FlushMode then the default value of AUTO will be used. So when you fire tempUuidDaoI.getAll() at the end of the test it makes hibernate flush before transaction ends, thus making changes visible for DBUnit checks.

Re-write testUpdateUuid in the following way and you will be surprised to find it working:

@Test
@ExpectedDatabase(value = "testUpdate.xml", assertionMode = DatabaseAssertionMode.NON_STRICT_UNORDERED)
public void testUpdateUuid() throws Exception {
TempUuid tu = tempUuidDaoI.get(1);
tu.setUuid("4b2f02ca-d857-4c95-b7fa-ee6283ce0d66");
tempUuidDaoI.update(tu);
tu = tempUuidDaoI.get(1);
assertEquals("4b2f02ca-d857-4c95-b7fa-ee6283ce0d66", tu.getUuid());
tempUuidDaoI.getAll();
}

The last line will force the flush.

As a workaround I would suggest flushing manually at the end of the test. session.flush() or entityManager.flush(). I wouldn’t rely on AUTO flush cause that’s not intuitive.

However it would be awesome if this problem could be fixed on the tesing framework level so that users wouldn’t have to worry about it.

0reactions
patient-developercommented, Nov 8, 2022

Hi, with the help of flush I was able to make an integration test work on service-level, e.g., see: service integration test

However, it does not work on Mvc-level, when testing the controller, e.g., see: controller integration test

Do you have any idea what is the issue with the MockMvc? Can you advice?

Thanks in advance!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Spring Data problem - derived delete doesn't work
The two methods do two different things: Long deleteBySystemId(String systemId); loads the entity by the given constraints and ends up issuing ...
Read more >
Spring Transaction Management: @Transactional In-Depth
Spring constructs a dynamic CGLib proxy of your UserService class here that can open and close database transactions for you. You or any...
Read more >
Spring Transactional – 5 Common Pitfalls | Codete Blog
It looks okay, but it won't work as someone expected. Since this is a transactional method, the user entity is in managed state...
Read more >
Page Data Is Inconsistent Error Message When Deleting My ...
When trying to save your page data, the system found that the information currently in the database did not match what was expected....
Read more >
Spring Data JPA - Reference Documentation
As the name suggests, the latter method issues a single JPQL query (the one defined in the annotation) against the database. This means...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found