【问题标题】:How to continue test after JUnit ExpectedException if thrown?如果抛出 JUnit ExpectedException,如何继续测试?
【发布时间】:2016-06-20 09:01:39
【问题描述】:

我已经使用 ExpectedException 功能设置了一些 JUnit (4.12) 测试,并且我希望在出现预期异常后继续测试。但我从来没有看到日志'3',因为执行似乎在异常之后停止,如果捕获事件?

这真的可能吗?如何实现?

@Rule
public ExpectedException exception = ExpectedException.none();

@Test
public void testUserAlreadyExists() throws Exception {
    log.info("1");

    // Create some users
    userService.createUser("toto1");
    userService.createUser("toto2");
    userService.createUser("toto3");
    Assert.assertTrue( userService.userExists("toto1") );
    Assert.assertTrue( userService.userExists("toto2") );
    Assert.assertTrue( userService.userExists("toto3") );

    log.info("2");

    // Try to create an existing user
    exception.expect(AlreadyExistsException.class);
    userService.createUser("toto1");

    log.info("3");
}

【问题讨论】:

  • 您可能需要重新考虑编写这样的测试,您希望在抛出异常后执行某些操作。如果您还想测试其他东西,那么您应该将它们分成两个不同的测试,一个检查异常,第二个检查另一个逻辑。

标签: java junit4 expected-exception junit-rule


【解决方案1】:

你不能这样做,当异常被抛出时,它会被真正抛出,ExpectedException 规则与否。

如果你真的想要这种行为,你可以回到“老派”模式:

try {
    userService.createUser("toto1");
    Assert.fail("expecting some AlreadyExistsException here")
} catch (AlreadyExistsException e) {
    // ignore
}

log.info("3");

但我不会为一些日志而烦恼。

【讨论】:

  • 好的,你确认我的想法,这是不可能的。正如@thepacker 所描述的,也许我的方法不是最好的。
【解决方案2】:

这个 SO 解决方案似乎做了你想做的事:JUnit continue to assert things after expected exception

我自己也在想类似的事情。要继续测试,您必须自己在测试中捕获异常。这个解决方案展示了一种优雅的方式。

注意:如果您制定规则以预期异常(如您所做的那样),则一旦抛出异常,测试将返回成功。 参考:http://junit.org/javadoc/latest/org/junit/rules/ExpectedException.html

【讨论】:

    【解决方案3】:

    如果您不想为具有许多选项以引发预期异常的事物添加大量类似的测试方法,并希望验证它是否真的在所有中的所需案例中引发一个单一的单元测试,我会建议这个(不是很可能)有用的模式:

    @Test
    public void testThatSomethingExpectedlyFails() {
        for (int i = 1; i <= 3; i++) {
            try {
                switch (i) {
                    case 1: // smth here throws the exception when configuration #1;
                    case 2: // smth here throws the exception when configuration #2;
                    case 3: // smth here throws the exception when configuration #3;
                }
            } catch (ExceptionThatIsExpected expected) {
                continue;
            } catch (Exception unexpected) {
                /* the test must fail when an unexpected exception is thrown */                
                fail("The test has failed due to an unexpected exception: " + unexpected.getMessage()); // or just re-throw this exception
            }
    
            /* the test must fail when a case completes without the expected exception */
            fail("No expected exception occurred at case " + i);
        }
    }
    

    它还可以迭代一些预先准备好的列表的项目(甚至执行函数),而不是使用硬编码整数的 switch-case。

    【讨论】:

      【解决方案4】:

      首先,您的测试并没有测试一件事。它在不同的条件下测试“userExists”和“createUser”,也就是不同的场景。这称为 AssertionRoulette。如果您要编写测试,那么您不需要破解即可继续记录“3”,因为正确的原因会失败。

      如果测试因正确的原因而失败,您可以在不执行所有日志记录的情况下查看失败的场景。 Junit-Runner 已经为您完成了日志记录。

      @Test
      public void testUserExists_UserCreatedUserNotExistent_expectTrue()
      {
         // Create some users
         userService.createUser("toto1");
      
         // Assert That user exists
         Assert.assertTrue( userService.userExists("toto1") );
      }
      
      @Test
      public void testCreateUser_UserAlreadyCreated_expectAlreadyExistsExceptionIsThrown()
      {
         // Create some users
         userService.createUser("toto1");
      
         // Try to create an existing user
         exception.expect(AlreadyExistsException.class);
         userService.createUser("toto1");    
      }
      

      【讨论】:

      • 由于 userService 在后面使用 MongoDB,这种方法的问题是一个测试方法已经初始化数据(createUser),而另一个测试将失败。或者我应该在每个测试方法之后清除数据库?
      • 您可以创建一个规则,为每个测试创建一个随机数并构建一个小的服务函数,这将创建一个唯一的名称。而不是“toto1”,它将变为“YzFAE4qd_toto1”。对于每个测试,您只需拥有不同的用户。不久前我看到了这种方法 - 但我不记得在哪里。如果我再次找到参考资料,会将其添加到我的答案中。
      • 上课后可以清空db。 @BeforeClass 和 @AfterClass 如果您需要,但规则也可以清理用户。可能性太多了。
      • 我有不同的看法——如果我想写一个集成测试怎么办?例如,我想检查我的应用程序是否在异常后清理了他的东西,所以你的声明“首先你的测试没有测试一件事”。并不总是正确的-这取决于-如果您编写单元测试这是合理的,如果集成测试-我不这么认为。
      猜你喜欢
      • 2018-03-31
      • 2014-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多