如果抛出JUnit ExpectedException后如何继续测试?

时间:2016-03-06 21:59:20

标签: java junit4 expected-exception junit-rule

我已经使用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 个答案:

答案 0 :(得分:9)

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

如果你真的想要这种行为,你可以回到旧学校"图案:

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

log.info("3");

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

答案 1 :(得分:3)

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

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

注意:如果您制定规则以期望异常(就像您所做的那样),则只要抛出该异常,测试就会返回成功。 参考:http://junit.org/javadoc/latest/org/junit/rules/ExpectedException.html

答案 2 :(得分:1)

首先,你的测试没有测试一件事。它在不同的条件下测试“userExists”和“createUser”a.k.a.不同的场景。这被称为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");    
}

答案 3 :(得分:1)

如果你不想为有很多选项的东西添加很多类似的测试方法来抛出预期的异常,并且想要验证它实际上是否会抛出所有所需的案例相反,我会建议这个(不太可能)有用的架构:

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