22

我已经使用 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");
}
4

4 回答 4

18

你不能这样做,当异常被抛出时,它是真实抛出的,不管ExpectedException规则与否。

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

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

log.info("3");

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

于 2016-03-06T22:06:50.470 回答
3

这个 SO 解决方案似乎做了你想做的事:JUnit 在预期异常后继续断言事情

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

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

于 2016-03-06T22:08:55.003 回答
2

如果您不想为具有许多选项的东西添加很多类似的测试方法来引发预期的异常,并且想要验证它实际上是否在单个单元测试中引发了所有期望的情况,我会建议这个(可能不是很漂亮)有用的模式:

@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。

于 2016-10-10T08:02:35.290 回答
1

首先,您的测试不会测试一件事。它在不同的条件下测试“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");    
}
于 2016-03-06T22:09:40.807 回答