8

The following test cases are functionally working properly, but one of the test methods having to create a new article in the database doesn't rollback at the end of the test case execution.
I expect it to work that way. For a test case that update article actually rollbacks the update at the end of test case execution.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "/applicationContext-test.xml")
@TransactionConfiguration(transactionManager = "txManager", defaultRollback = true)
@Transactional
public class PriceRepositoryTest {

@Resource(name ="repository")
private PriceRepository repository;
@Test
public void testGetAll() throws Exception {
    Assert.assertEquals(8, repository.getAll().size());
}


@Test
@Rollback
public void shouldSaveNewArticle(){
    Article article = new Article();
    article.setName("Article");
    article.setPrice(33);
    repository.save(article);

    Assert.assertEquals(9, repository.getAll().size());
}


@Test
@Rollback
public void shouldUpdateArticle(){
    Article article = repository.getArticle(4);
    article.setPrice(33);
    repository.update(article);

    Assert.assertEquals(String.valueOf(33.0), String.valueOf(repository.getArticle(4).getPrice()));
}

}

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
Antony
  • 1,608
  • 1
  • 20
  • 27

3 Answers3

5

Is your DAO perhaps also marked with @Transactional? If it is, that's the problem: the transactionality on a different layer doesn't know about your local transaction configuration. If repository.update(article) is @Transactional, it may or may not start a new transaction (depending on the value of the propagation attribute), but it will commit the transaction after execution, and there's nothing your test method can do to intercept that.

That's one of the reasons why transactions should be started on the service level, not the DAO level.

(If that's not the case, I humbly apologize)

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • if you actually look at the code both the update and save methods are marked Propagation.REQUIRED. – Antony Feb 14 '11 at 13:10
  • @Antony see these Questions: http://stackoverflow.com/questions/1079114/spring-transactional-annotation-best-practice http://stackoverflow.com/questions/3886909/where-should-transactional-be-place-service-layer-or-dao – Sean Patrick Floyd Feb 14 '11 at 17:00
1

I also encountered this issue and spent some hours trying to find the root cause. The issue was a variant of the problems described here. In my case, the application calls stored procedures through Spring, and one of these procedures contained a COMMIT statement.

Commits should always be controlled by the app, if there is a stray commit somewhere in a stored procedure, Spring can't control the transaction and tests won't roll back.

lucrussell
  • 5,032
  • 2
  • 33
  • 39
0

I just encountered this with my unit tests all set to rollback and my record was still showing up in the database after the test finished. The reason was there was that in the DAO a call to the entitymanager to flush() was in the method - which forced the transaction to commit.

em.persist(jpaServer); em.flush(); //commits the record no matter what spring is setup to do

taking the flush out and confirmed no record. Tested the same code with the test annotated to @Rollback(false) and confirmed the record (proving the flush was not needed)

  • Ben www.nimbits.com
bsautner
  • 4,479
  • 1
  • 36
  • 50
  • flush() will push pending updates to the db, but it does not force a commit, they should still rollback (unless you have autocommit on) – dan carter Oct 29 '15 at 04:46