21

我有

@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
   }

我的问题是:mySetup、testMy 和 myTeardown 会在同一个事务中运行吗?看起来他们应该这样做,但我遇到了一些奇怪的错误,这可能表明他们正在互相踩踏。

4

3 回答 3

29

是的,所有三种方法都将在同一个事务中运行。请参阅参考文档中的TestContext 框架/事务管理部分:

任何 before 方法(例如使用 JUnit 的 @Before 注释的方法)和任何 after 方法(例如使用 JUnit 的 @After 注释的方法)都事务中执行

因此, and上的@Transactional注释有点多余,甚至可能被认为具有误导性,因为它们的事务性是由当前正在执行的单个测试方法确定的。mySetup()myTeardown()

这是因为(负责启动/完成事务)的beforeTestMethod()afterTestMethod()回调分别在 JUnit 的方法之前和 JUnit 的方法之后执行。TransactionalTestExecutionListener@Before@After

于 2013-06-25T22:36:27.167 回答
8

Spring 5 发生了一些变化。根据文档

方法级别的生命周期方法——例如,使用 JUnit Jupiter 的@BeforeEach@AfterEach注释的方法——在测试管理的事务中运行。

另一方面,套件级和类级生命周期方法——例如,使用 JUnit Jupiter 的@BeforeAll@AfterAll注释的方法以及使用 TestNG 的@BeforeSuite@AfterSuite、 @BeforeClass或@AfterClass注释的方法——不在内部运行一个测试管理的事务

如果您需要在事务中执行套件级或类级生命周期方法中的代码,您可能希望将相应的PlatformTransactionManager注入您的测试类,然后将其与TransactionTemplate 一起用于程序化事务管理

于 2020-05-30T09:03:25.127 回答
3

如果您使用@Transactional 注释您的@Before 和@After 方法,它们将不会在事务中运行。但是,如果您将@Transactional 用于您的测试方法(带有@Test 的方法)或整个测试类,则每个测试方法都将在不同的事务中运行,@Before 和@After 方法也将在相同的事务中运行每个@Test 方法的事务。有关更多说明,请参阅以下两个代码片段:

@Transactional
public class MyTestClass {
    @Before
    public void beforeTest() {
        ...
    }

    @Test
    void testMethod1() {
        ...
    }

    @Test
    void testMethod2() {
        ...
    }

    @After
    public void afterTest() {
        ...
    }
}

上面的代码运行方式与下面的代码完全相同:

public class MyTestClass {
    @Before
    public void beforeTest() {
        ...
    }

    @Test
    @Transactional
    void testMethod1() {
        ...
    }

    @Test
    @Transactional
    void testMethod2() {
        ...
    }

    @After
    public void afterTest() {
        ...
    }
}

在每个“testMethod1”和“testMethod2”方法的这两个代码片段中,都会有不同的事务。而且“beforeMethod”和“afterMethod”方法都将分别在每个测试方法的事务中运行。

于 2018-12-26T10:40:02.993 回答