I have
@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration(defaultRollback = true, transactionManager = "transactionManager")
@Before
@Transactional
public void mySetup() {
// insert some records in db
}
@After
@Transactional
public void myTeardown() {
// delete some records
}
@Test
@Transactional
public void testMy() {
// do stuff
}
My question is: will mySetup, testMy and myTeardown all run within the same transaction? It seems like they should, but I'm getting some strange error which might suggest that they are stepping on each other.
Yes, all three methods will run within the same transaction. See section TestContext Framework/Transaction management in the reference docs:
Any before methods (such as methods annotated with JUnit's @Before) and any after methods (such as methods annotated with JUnit's @After) are executed within a transaction
Thus the @Transactional
annotation on mySetup()
and myTeardown()
is kind of redundant, or might be even considered misleading, as their transactionality is determined by the individual test method being currently executed.
This is because the beforeTestMethod()
and afterTestMethod()
callbacks of TransactionalTestExecutionListener
(responsible for starting/completing the transaction) are executed before JUnit's @Before
and after JUnit's @After
methods, respectively.
If you annotate your @Before and @After methods with @Transactional, they will not be run in a transaction. But if you use @Transactional for your test methods (methods that have @Test on them) or your test class as a whole, every test method will be run in different transaction and @Before and @After methods will also be run in the same transaction as for each @Test method. For more illustration, see these two code snippets:
@Transactional
public class MyTestClass {
@Before
public void beforeTest() {
...
}
@Test
void testMethod1() {
...
}
@Test
void testMethod2() {
...
}
@After
public void afterTest() {
...
}
}
The above code runs in exactly the same way as the below code:
public class MyTestClass {
@Before
public void beforeTest() {
...
}
@Test
@Transactional
void testMethod1() {
...
}
@Test
@Transactional
void testMethod2() {
...
}
@After
public void afterTest() {
...
}
}
In these two code snippets for each "testMethod1" and "testMethod2" methods there would be a different transaction. And also both "beforeMethod" and "afterMethod" methods would be run in each test method's transaction respectively.