Java JUnit 测试总是回滚事务

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9817388/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 08:04:13  来源:igfitidea点击:

JUnit tests always rollback the transactions

javaspringjunit4

提问by Juan

I'm running a simple JUnit test agains an application DAO. The problem is that I always get:

我正在对应用程序 DAO 运行一个简单的 JUnit 测试。问题是我总是得到:

javax.persistence.RollbackException: Transaction marked as rollbackOnly

The JUnit test is:

JUnit 测试是:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:com/my/app/context.xml"}
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
@Transactional
public class PerformanceTest {

    @Test
    @Transactional(propagation= Propagation.REQUIRES_NEW)
    @Rollback(false)
    public void testMsisdnCreationPerformance() {
        // Create a JPA entity

        // Persist JPA entity
    }
}

As you can see I'm declaring clearly not to rollback this method.

如您所见,我明确声明不回滚此方法。

Does Spring JUnit support always sets rollback to true?

Spring JUnit 支持是否总是将回滚设置为 true?

回答by Snicolas

It is strange to desire a test that changes your database and keep the modification. Tests are supposed to be orthogonal : no test depends on an other. Moreover, tests are supposed to be independent of tests order, and even idempotent.

想要一个改变你的数据库并保持修改的测试是很奇怪的。测试应该是正交的:没有测试依赖于另一个。此外,测试应该独立于测试顺序,甚至是幂等的

So either you want to change you data base in your setUp()method and rollback the change in your tearDown()method, either you want to setup a test database with some good values in it for tests.

因此,要么您想更改setUp()方法中的数据库并回滚方法中的更改tearDown(),要么您想设置一个测试数据库,其中包含一些用于测试的良好值。

Maybe I am missing something here but usually you should not want that.

也许我在这里遗漏了一些东西,但通常你不应该想要那样。

回答by Ralph

It should work, like you expect it, but may be you open another transaction within your class under test or you have an other feature/or bug somewhere.

它应该可以正常工作,就像您期望的那样,但可能是您在测试类中打开了另一个事务,或者您在某处有其他功能/或错误。

Btw this annotations should be enougth:

顺便说一句,这个注释应该足够了:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:com/my/app/context.xml"}
@Transactional
public class PerformanceTest {

    @Test
    @Rollback(false)
    public void testMsisdnCreationPerformance() {
        // Create a JPA entity

        // Persist JPA entity
    }
}

@See Spring Reference Chapter 9.3.5.4 Transaction management

@参见Spring 参考章节 9.3.5.4 事务管理

回答by AL3X

I agree the Ralph's answer.

我同意拉尔夫的回答。

The Propagation.REQUIRES_NEWcreates a new transaction and this probably does not match with the main transactional route in which the test is running.

Propagation.REQUIRES_NEW创建一个新的交易,这可能不会在测试运行的主要交易途径相匹配。

In my simple experience the annotation @Transactionalwill properly work to define the transactional context in which every single test should run, delegating to this one the specific current Rollback clause (as shown by Ralph).

根据我的简单经验,注释@Transactional将正常工作以定义每个测试应该在其中运行的事务上下文,将特定的当前回滚子句委托给这个子句(如 Ralph 所示)。

The Ralph's answer is useful and in the same time the Snicolas's answer concerns a particular case of managing context of tests. The idempotenceis fundamental for integration and automatic tests, but should be different ways to implements them. The question is, which kind of methods do you have? And what behavior do theese methods have?

Ralph 的回答很有用,同时 Snicolas 的回答涉及管理测试上下文的特殊情况。该幂等是集成和自动测试的基础,而应该是不同的方式来实现它们。问题是,你有哪些方法?这些方法有什么行为?

   [...]
   @Transactional

   public class Test {

   @Test
   @Rollback(false)
   public void test() {

   [...]

Is the simple, question-coherent way :)

是简单的,问题连贯的方式:)

回答by grep

Just add annotation Rollback and set the flag to false.

只需添加注释回滚并将标志设置为false。

   @Test
   @Rollback(false)

回答by harryssuperman

From official Documentation:

来自官方文档:

By default, test transactions will be automatically rolled back after completion of the test; however, transactional commit and rollback behavior can be configured declaratively via the @Commit and @Rollback annotations

默认情况下,测试事务会在测试完成后自动回滚;但是,事务提交和回滚行为可以通过@Commit 和@Rollback 注释以声明方式配置

https://docs.spring.io/spring/docs/current/spring-framework-reference/html/integration-testing.html#integration-testing-annotations

https://docs.spring.io/spring/docs/current/spring-framework-reference/html/integration-testing.html#integration-testing-annotations

@Commit indicates that the transaction for a transactional test method should be committed after the test method has completed. @Commit can be used as a direct replacement for @Rollback(false) in order to more explicitly convey the intent of the code.

@Commit 表示应在测试方法完成后提交事务性测试方法的事务。@Commit 可用作 @Rollback(false) 的直接替代品,以便更明确地传达代码的意图。

回答by Vicky

I use Junit5, both commit and rollback(false) works with me.

    @ExtendWith(SpringExtension.class)
    @SpringBootTest
    @Transactional
    public class MyIntegrationTest {

      @Test
      @DisplayName("Spring Boot Will Rollback Data, " +
      "Can Disable it By Add @Commit Or @Rollback(false) Annotation")
      //@Commit
      //@Rollback(false)
      public void test() throws Exception {
       //your test codes here...
      }