【问题标题】:@BeforeAll and @Transaction are not working - changes on db side are not rollbacked@BeforeAll 和 @Transaction 不起作用 - 数据库端的更改不会回滚
【发布时间】:2019-11-01 10:23:59
【问题描述】:

我正在尝试使用@Transactional 在测试后回滚并使用@BeforeAll 设置测试对象来测试我的应用程序:

@EnableJpaRepositories
@SpringBootTest
@Transactional
public class UserScoreTest {
    @BeforeAll
    public static void init() {
       userRepository.save(user);
    }

    @Test
    ...
}

问题似乎是一旦执行@BeforeAll,更改就“提交”了。

有人知道这是期望的行为还是错误?

我使用@BeforeEach 解决了我的问题,然后在@Test 中保存,它可以工作(测试后,所有内容都回滚)但我更愿意使用@BeforeAll 设置一次。

【问题讨论】:

    标签: java spring junit


    【解决方案1】:

    我相信您的问题是 @Transactional 仅适用于 Spring“Bean”的实例方法,而不适用于静态方法。这就是为什么它适用于 @BeforeEach 实例方法但不适用于 @BeforeAll 静态方法的原因。

    解决此问题的一种方法是使用@BeforeEach,但有一个布尔字段来存储是否已经完成一次。如果您的测试以多线程方式运行,请不要忘记解决线程问题。

    This answer 解释得更好。

    【讨论】:

      【解决方案2】:

      我认为你的概念是错误的。

      在常见的测试场景中,任何 @Autowired 依赖项,例如您的 userRepository,都不应是静态的。我想它是静态的,因为您从静态方法中引用它。

      您应该只考虑@Before 注释,并且由于@Transactional 注释,每个测试将在结束时自动回滚。

      主要场景是这样的:

      运行@BeforeAll

      对于每个@Test 注解:

      • 开始交易
      • 运行@Before
      • 运行@Test
      • 运行@After
      • 回滚交易

      @BeforeAll 的目的是为整个测试类只做一次工作。我可以想到为 RequestContextHolder 或 SecurityContextHolder 设置值的一种可能方案,但我会意识到在其他线程中丢失这些值(如果 @Test 创建一些)。我很少使用@BeforeAll。同样的原则也适用于 @Parameterized 测试,它必须在静态方法上方有 @Parameters 注释。这是因为@RunWith 中的运行程序必须知道在实际初始化测试之前要使用多少个测试以及要使用哪些参数。

      @BeforeAll 超出事务范围。

      【讨论】:

      • 感谢您的帮助。我使用“@BeforeAll”来创建可以在所有测试中使用的 bean。前任。创建 2 个玩家,创建一个游戏,然后进行不同的测试。在每次测试之前创建玩家,一个游戏是没有意义的,所以我认为使用它并没有错,但它在这里不起作用。正如“@John B”所说,解决方法是使用布尔值创建“@BeforeEach”并只执行一次
      【解决方案3】:

      @BeforeEach 对每个@Test 执行一次,@BeforeAll 在所有@Test 启动时只执行一次

      【讨论】:

      • 没错,但这不是我问题的答案,这更像是评论而不是答案。
      猜你喜欢
      • 2017-03-27
      • 1970-01-01
      • 2017-07-22
      • 2018-09-15
      • 1970-01-01
      • 2014-05-15
      • 1970-01-01
      • 2015-11-14
      • 1970-01-01
      相关资源
      最近更新 更多