Rollback transaction after @Test

JavaSpringHibernateJunitSpring Test

Java Problem Overview


First of all, I've found a lot of threads on StackOverflow about this, but none of them really helped me, so sorry to ask possibly duplicate question.

I'm running JUnit tests using spring-test, my code looks like this

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = {})
public class StudentSystemTest {

	@Autowired
	private StudentSystem studentSystem;

    @Before
	public void initTest() {
    // set up the database, create basic structure for testing
    }

    @Test
	public void test1() {
    }    
    ...  
}

My problem is that I want my tests to NOT influence other tests. So I'd like to create something like rollback for each test. I've searched a lot for this, but I've found nothing so far. I'm using Hibernate and MySql for this

Java Solutions


Solution 1 - Java

Just add @Transactional annotation on top of your test:

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = {"testContext.xml"})
@Transactional
public class StudentSystemTest {

By default Spring will start a new transaction surrounding your test method and @Before/@After callbacks, rolling back at the end. It works by default, it's enough to have some transaction manager in the context.

From: 10.3.5.4 Transaction management (bold mine):

> In the TestContext framework, transactions are managed by the TransactionalTestExecutionListener. Note that TransactionalTestExecutionListener is configured by default, even if you do not explicitly declare @TestExecutionListeners on your test class. To enable support for transactions, however, you must provide a PlatformTransactionManager bean in the application context loaded by @ContextConfiguration semantics. In addition, you must declare @Transactional either at the class or method level for your tests.

Solution 2 - Java

Aside: attempt to amend Tomasz Nurkiewicz's answer was rejected: > This edit does not make the post even a little bit easier to read, easier to find, more accurate or more accessible. Changes are either completely superfluous or actively harm readability.

Solution 3 - Java

The answers mentioning adding @Transactional are correct, but for simplicity you could just have your test class extends AbstractTransactionalJUnit4SpringContextTests.

Solution 4 - Java

I know, I am tooooo late to post an answer, but hoping that it might help someone. Plus, I just solved this issue I had with my tests. This is what I had in my test:

My test class

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "path-to-context" })
@Transactional
public class MyIntegrationTest 

Context xml

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
   <property name="driverClassName" value="${jdbc.driverClassName}" />
   <property name="url" value="${jdbc.url}" />
   <property name="username" value="${jdbc.username}" />
   <property name="password" value="${jdbc.password}" />
</bean>

I still had the problem that, the database was not being cleaned up automatically.

Issue was resolved when I added following property to BasicDataSource

<property name="defaultAutoCommit" value="false" />

Hope it helps.

Solution 5 - Java

In addition to adding @Transactional on @Test method, you also need to add @Rollback(false)

Solution 6 - Java

You need to run your test with a Spring context and a transaction manager, e.g.,

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = {"/your-applicationContext.xml"})
@TransactionConfiguration(transactionManager="txMgr")
public class StudentSystemTest {

     @Test
     public void testTransactionalService() {
         // test transactional service
     }

     @Test
     @Transactional
     public void testNonTransactionalService() {
         // test non-transactional service
     }
}

See chapter 3.5.8. Transaction Management of the Spring reference for further details.

Solution 7 - Java

You can disable the Rollback:

@TransactionConfiguration(defaultRollback = false)

Example:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@Transactional
@TransactionConfiguration(defaultRollback = false)
public class Test {
    @PersistenceContext
    private EntityManager em;

    @org.junit.Test
    public void menge() {
	    PersistentObject object = new PersistentObject();
	    em.persist(object);
	    em.flush();
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJan VorcakView Question on Stackoverflow
Solution 1 - JavaTomasz NurkiewiczView Answer on Stackoverflow
Solution 2 - Javauser2418306View Answer on Stackoverflow
Solution 3 - Javamatt bView Answer on Stackoverflow
Solution 4 - JavaAtul KumbharView Answer on Stackoverflow
Solution 5 - Javauser2615724View Answer on Stackoverflow
Solution 6 - JavaJohan SjöbergView Answer on Stackoverflow
Solution 7 - JavaDwDView Answer on Stackoverflow