@NotTransactional alternatives

junit, mybatis, spring

Solution

`@Rollback(false)` isn't always sufficient, it only means the transaction won't be rolled back at the end of test. But it still runs the test in a transaction, which sometimes lead to conflicts with other running transactions.

As Spring suggest, you have two options:

- Split the test class into two, the transactional tests can be a in test class annotated with `@Transactional`, while the non-transactional test in a test class without transactional annotation.

- Use method annotations instead of class annotation, annotate each transaction test with `@Transactional`, but remove it from the class scope

Quoting Spring documentation:

As of Spring 3.0, `@NotTransactional` is deprecated in favor of moving the non-transactional test method to a separate (non-transactional) test class or to a `@BeforeTransaction` or `@AfterTransaction` method. As an alternative to annotating an entire class with `@Transactional`, consider annotating individual methods with `@Transactional`; doing so allows a mix of transactional and non-transactional methods in the same test class without the need for using `@NotTransactional`.

Problem

I'm working on a unit test which commits information through a DAO to a Oracle database, and then retrieves it and checks everything is unchanged. There are other unit tests in the test class, and at the top of the class I have: ``` @TransactionConfiguration (defaultRollback = true) ``` I'd like to know how I can remove the @NotTransactional. I'm not specifying Transactional on the class, so no tests should be like that by default. Since this is it's own test, I don't know if the @BeforeTransaction (or After) annotations would be correct. The biggest problem is that without the @NotTransactional, it appears as though the unsubscribe() function isn't ran. (the trash flag is unchanged.) Running the test again, with @rollback=false and @NonTransactional present, I see the trash flag correctly set to true, in the database after the test is finished. ``` @RunWith (SpringJUnit4ClassRunner.class) @TransactionConfiguration (defaultRollback = true) public class DatabaseTest { @Autowired (required = true) private FooDao<Foo> fooDao; @Autowired (required = true) private FooService fooService; // other tests here that are marked @Transactional. @Test @NotTransactional public void testDelete() { Foo foo = new foo(); foo.setTrashFlag(false); foo.setId(123); fooDao.create(foo); Foo fooFromDb = fooService.getFromDbById(123); assertNotNull(fooFromDb); fooService.unsubscribe(123); // among other things, // **sets trash flag to true.** // sqlSession.flushStatements(); // doesn't seem to commit the unsubscribe action // getFromDbById() returns ONLY Foos with trash set to false, so we expect // nothing returned here as we've just set trash to true, using unsubscribe(). Foo trashedFoo = fooService.getFromDbById(123); assertNull(trashedFoo); ``` Thanks!

Original source