【问题标题】:@Before and @Transactional@Before 和 @Transactional
【发布时间】:2013-06-22 21:35:16
【问题描述】:

我有

@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 会在同一个事务中运行吗?看起来他们应该这样做,但我遇到了一些奇怪的错误,这可能表明他们正在互相踩踏。

【问题讨论】:

    标签: java spring unit-testing junit


    【解决方案1】:

    Spring 5 发生了一些变化。 根据the documentation

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

    另一方面,套件级和类级生命周期方法——例如, 用 JUnit Jupiter 的 @BeforeAll@AfterAll 注释的方法和用 TestNG 的 @BeforeSuite@AfterSuite@AfterSuite 注释的方法strong>@BeforeClass 或 @AfterClass - 不在测试管理的事务中运行

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

    【讨论】:

    • 感谢有关 PlatformTransactionManager 的提示!给我线索以取得进展:-)(不错的baeldung 文章)
    【解决方案2】:

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

    @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() {
            ...
        }
    }
    

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

    【讨论】:

      【解决方案3】:

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-11-11
        • 2017-11-08
        • 2023-03-10
        • 2019-03-27
        • 1970-01-01
        • 1970-01-01
        • 2018-02-14
        相关资源
        最近更新 更多