当前位置: 首页 > 知识库问答 >
问题:

将@Transactional与@Commit一起使用时无法测试预期的异常

洪季萌
2023-03-14

我使用的是Spring Boot 1.4.0。M3。

我有一个@实体,它有一个用户名,应该是唯一的:

@NotNull
@Column(unique = true)
@Pattern(regexp = "[a-zA-Z_\\-\\.0-9]+")
@Size(min = 1, max = 30)
private String username;

使用Spring数据存储库,我想测试使用重复用户名时是否会出现异常。此测试工作:

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

    @Autowired
    private UserRepository repository;

    @Test(expected = DataIntegrityViolationException.class)
    public void test() {
        repository.save(User.createAdmin(repository.nextId(), "wim", "123456"));
        repository.save(User.createAdmin(repository.nextId(), "wim", "123456"));
    }
}

但是,当使用@Commit添加@Transactional时,此测试失败:

@SpringBootTest
@RunWith(SpringRunner.class)
@Transactional
public class UserRepositoryIntegrationTest {

    @Autowired
    private UserRepository repository;

    @Test(expected = DataIntegrityViolationException.class)
    @Commit
    public void test() {
        repository.save(User.createAdmin(repository.nextId(), "wim", "123456"));
        repository.save(User.createAdmin(repository.nextId(), "wim", "123456"));
    }
}

但是查看日志,会抛出DataIntegrityViolationException

2016-05-24 09:05:16.619错误22790---[主]o.h.发动机。jdbc。spi。SqlExceptionHelper:唯一索引或主键冲突:“UK_D8HGQ87BS4VPMC81NQ9G69G8X_索引位于PUBLIC.MYPROJECT_用户(用户名)值('wim',1');SQL语句:在myproject_用户(密码、用户名、角色、id)中插入值(?、、‘ADMIN’、?)[23505-191]2016-05-24 09:05:16.620信息22790---[
main]o.h.e.j.b.内部。AbstractBatchImpl:HHH000010:batch发布时,它仍然包含JDBC语句2016-05-24 09:05:16.629 WARN 22790---[main]o.s.测试。上下文TestContextManager
:允许TestExecutionListener[org.springframework.test.context.transaction]时捕获异常。TransactionalTestExecutionListener@589b3632]要处理测试的“之后”执行:方法[public void com.spring.boot.test.user.UserRepositoryIntegrationTest.test()],实例[com.spring.boot.test.user]。UserRepositoryIntegrationTest@3ca278bc],异常[java.lang.AssertionError:预期异常:org.springframework.dao.DataIntegrityViolationException]

为什么测试失败?JUnit是否会在Spring提交事务之前检查是否抛出异常?

共有3个答案

阚乐湛
2023-03-14

我需要在MVC控制器测试(@WebAppConfiguration)中测试DataBuilityViolationExc0019,并通过@ControlllerAdwn在应用程序内部进行@响应状态修改。所以你的方法不适合我,冲得太晚了。不幸的是@NotTransactional注释在Spring 4中被排除在外,所以我只是将@Transactional的测试与非事务性测试分开。另见http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/testing.html#integration-testing-annotations

@不推荐使用NotTransactional

使现代化2种解决方案:

  • 明确区分事务性和非事务性测试
王俊哲
2023-03-14

根据M. Deina和Stephane Nicoll的评论,这是工作版本:

@SpringBootTest
@RunWith(SpringRunner.class)
@Transactional
public class UserRepositoryIntegrationTest {

    @Autowired
    private UserRepository repository;

    @Test(expected = DataIntegrityViolationException.class)
    public void test() {
        repository.save(User.createAdmin(repository.nextId(), "wim", "123456"));
        repository.save(User.createAdmin(repository.nextId(), "wim", "123456"));

        TestTransaction.flagForCommit();
        TestTransaction.end();
    }
}

请注意,需要调用这两个静态方法才能使其正常工作。

梁明辉
2023-03-14

你不需要promise。您只需要将您的工作单元刷新到数据库,就可以看到DataBuilityViolationExc0019

这在《Spring参考手册》中关于“假阳性”的注释中有所描述。但是,请注意,必须通过@PeristextContext注入EntityManager(而不是@autowled)。

以下内容对您来说应该很好:

java prettyprint-override">@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class UserRepositoryIntegrationTest {

    @Autowired
    UserRepository repository;

    @PersistenceContext
    EntityManager entityManager;

    @Test(expected = DataIntegrityViolationException.class)
    public void test() {
        repository.save(User.createAdmin(repository.nextId(), "wim", "123456"));
        repository.save(User.createAdmin(repository.nextId(), "wim", "123456"));

        entityManager.flush();
    }
}

当做

Sam(SpringTestContext框架的作者)

 类似资料:
  • 我使用数据提供者方法和测试方法(测试方法中带有ITestContext参数)。一个简化的例子如下: 我的Retry类和RetryListener类如下: } 预期:当测试失败时,TestNG调用重试,然后数据提供程序应将相同的值返回给测试方法。 观察到:数据提供者返回相同的值,但测试方法没有运行,重试终止,下一个测试开始(数据提供者现在将返回新值) 但我的重试没有输入测试方法(测试方法不需要(in

  • 主要内容:1. 运行时异常,2. 检查异常在本教程中,我们将演示如何使用TestNG expectedExceptions来测试代码中的预期异常抛出。 创建一个名称为 ExpectedExceptionTest 的 Maven 工程,其结构如下所示 - 1. 运行时异常 此示例显示如何测试运行时异常。 如果方法抛出一个运行时异常 — ,它会获得通过。 创建一个测试文件:TestRuntime.java ,其代码如下所示 - 运行上面代码,

  • 我目前正在将IntelliJ IDE用于复杂的GWT项目。我想在GWT的开发模式中利用JRebel,所以最近我为IntelliJ安装了JRebel插件,但在使其工作时遇到了麻烦。 基本上IntelliJ不具备在更改时自动编译应用程序的能力,所以每当您对代码进行更改时,我都必须进行编译- 信息:使用JavaC1.7.0_21编译java源代码信息:15个错误信息:0个警告信息:编译完成,9分钟5秒内

  • 我想测试某个异常是用作为JUnit测试方法的某个部分中的异常原因抛出的。 测试方法本身不应该抛出异常--只是它的一个特定部分。

  • 问题内容: 我在该领域做了一些谷歌搜索,发现了很多有关让Jenkins理解boost.test的XML输出格式的讨论,但是没有规范的参考。 有人说我们只需要使用XLST来转换XML格式,另一些人则认为XML在此之前需要进行一些修改有人拥有XSL来将Boost.TestXML日志转换为可显示的格式吗?)。有些人建议xUnit插件可以原生理解boost.test XML格式,另一些人则认为它不能 因为

  • 我最近安装了Xcode8测试版5。在我的MAC 10.11.6上的Appium 1.6.0测试版现在,在阅读了所有的论坛并使Appium启动并启动我的应用程序后,我无法找到如何用这个Appium 1.6.0测试版启动我的inspector和在我的应用程序中找到元素。如何使用appium 1.6.0测试版启动inspector?如果不能,我们如何找到xpath或找到元素??