Spring @transaction not working as expected in junit in non debug mode
hibernate, java, junit, spring, transactions
Solution
Had similar issue, but in my case it did not rollback. It seems that you forgot to add @Transactional. From documentation (link)
Transaction management
In the TestContext framework, transactions are managed by the TransactionalTestExecutionListener which is configured by default, even if you do not explicitly declare @TestExecutionListeners on your test class. To enable support for transactions, however, you must configure a PlatformTransactionManager bean in the ApplicationContext that is loaded via @ContextConfiguration semantics (further details are provided below). In addition, you must declare Spring’s @Transactional annotation either at the class or method level for your tests.
Here is example form the link above.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@TransactionConfiguration(transactionManager="txMgr", defaultRollback=false)
@Transactional
public class FictitiousTransactionalTest {
@BeforeTransaction
public void verifyInitialDatabaseState() {
// logic to verify the initial state before a transaction is started
}
@Before
public void setUpTestDataWithinTransaction() {
// set up test data within the transaction
}
@Test
// overrides the class-level defaultRollback setting
@Rollback(true)
public void modifyDatabaseWithinTransaction() {
// logic which uses the test data and modifies database state
}
@After
public void tearDownWithinTransaction() {
// execute "tear down" logic within the transaction
}
@AfterTransaction
public void verifyFinalDatabaseState() {
// logic to verify the final state after transaction has rolled back
}
}
Problem
All MyService methods are transactional. The junit test below, gets count of items, saves a new item, and gets count of items to make sure that counts has been incremented by 1. ``` public class MyTest extends ServiceTest{ 1. int countBefore = myService.getCount(); //return n 2. myService.add(item); //item is really added to DB 3. int countAfter = myService.getCount(); //return n (sometimes n+1) } @Transactional(propagation=Propagation.REQUIRES_NEW, isolation=Isolation.READ_COMMITTED) getCount(){…} @Transactional(propagation=Propagation.REQUIRES_NEW, isolation=Isolation.SERIALIZABLE) add(){…} ``` ``` @Ignore @ContextConfiguration(locations = { "file:src/main/resources/xxx-context.xml", "file:src/main/resources/xxx-data.xml", "file:src/main/resources/xxx-services.xml" }) @TransactionConfiguration(transactionManager = "txManager", defaultRollback = false) @TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class, TransactionalTestExecutionListener.class, TestListener.class}) public class ServiceTest extends AbstractUT{ ``` ``` @Ignore @RunWith(SpringJUnit4ClassRunner.class) @TestExecutionListeners( {TestListener.class}) public class AbstractUT{ ``` When debugging (3.) returns n+1 which is what I want. But when running the test without debug I get n. Even sometimes when running the test I get n+1 and next time I get n and when comparing the std output between the two execution, it looks exactly the same. I have enabled log4j.logger.org.springframework.transaction=TRACE and I can see: ``` Initializing transaction synchronization Getting transaction for MyService.getCount ... Completing transaction for MyService.getCount Clearing transaction synchronization ... Initializing transaction synchronization Getting transaction for MyService.add ... Completing transaction for MyService.add Clearing transaction synchronization ... Initializing transaction synchronization Getting transaction for MyService.getCount ... Completing transaction for MyService.getCount Clearing transaction synchronization ``` So transactions are being executed one after the other, but how is possible that (3.) don't see the saved item? Transaction managment is setup in my test class as per: https://stackoverflow.com/a/28657650/353985 How can I find what is going wrong? Thanks!