繁体   English   中英

如何在 Spring Boot 测试中强制事务提交?

[英]How to force transaction commit in Spring Boot test?

如何在运行方法时而不是在方法之后强制在 Spring Boot(使用 Spring Data)中提交事务?

我在这里读到,在另一个类中使用@Transactional(propagation = Propagation.REQUIRES_NEW)应该是可能的,但对我不起作用。

任何提示? 我正在使用 Spring Boot v1.5.2.RELEASE。

@RunWith(SpringRunner.class)
@SpringBootTest
public class CommitTest {

    @Autowired
    TestRepo repo;

    @Transactional
    @Commit
    @Test
    public void testCommit() {
        repo.createPerson();
        System.out.println("I want a commit here!");
        // ...
        System.out.println("Something after the commit...");
    }
}

@Repository
public class TestRepo {

    @Autowired
    private PersonRepository personRepo;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void createPerson() {
        personRepo.save(new Person("test"));
    }
}

一种方法是在测试类中注入TransactionTemplate ,删除@Transactional@Commit并将测试方法修改为:

...
public class CommitTest {

    @Autowired
    TestRepo repo;

    @Autowired
    TransactionTemplate txTemplate;

    @Test
    public void testCommit() {
        txTemplate.execute(new TransactionCallbackWithoutResult() {

          @Override
          protected void doInTransactionWithoutResult(TransactionStatus status) {
            repo.createPerson();
            // ...
          }
        });

        // ...
        System.out.println("Something after the commit...");
    }

或者

new TransactionCallback<Person>() {

    @Override
    public Person doInTransaction(TransactionStatus status) {
      // ...
      return person
    }

    // ...
});

而不是TransactionCallbackWithoutResult回调 impl 如果您计划向刚刚持久化的 person 对象添加断言。

使用辅助类org.springframework.test.context.transaction.TestTransaction (自 Spring 4.1 起)。

默认情况下会回滚测试。 要真正承诺一个人需要做的

// do something before the commit 

TestTransaction.flagForCommit(); // need this, otherwise the next line does a rollback
TestTransaction.end();
TestTransaction.start();

// do something in new transaction

并且请不要在测试方法上使用@Transactional 如果您忘记了,开始在你的业务代码事务, @Transactional测试绝不会检测到它。

使用 lambda 的解决方案。

@Autowired
TestRepo repo;

@Autowired
TransactionTemplate txTemplate;

private <T> T doInTransaction(Supplier<T> operation) {
    return txTemplate.execute(status -> operation.get());
}

private void doInTransaction(Runnable operation) {
    txTemplate.execute(status -> {
        operation.run();
        return null;
    });
}

用作

Person saved = doInTransaction(() -> repo.save(buildPerson(...)));

doInTransaction(() -> repo.delete(person));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM