37

我正在尝试对其他人编写的代码进行 JUnit 测试,但我无法弄清楚如何测试异常,因为异常似乎缺少类型。

public Pirate(String name, int initialGold) throws Exception {
    if(initialGold < 0)
        throw new Exception("Init Gold must be >= 0");
    this.name = name;
    this.numGold = initialGold;
    this.health = Pirate.DEFAULT_HEALTH;
    this.isCursed = false;
}

我的 JUnit 代码片段:

@Test
public static void constructorTest() throws Exception{
    rodgers = new Pirate("Dread Pirate Rodgers", 10000);
    assertEquals("Dread Pirate Rodgers" , rodgers.getName());
    assertEquals(10000, rodgers.getNumGold());
    assertEquals(100, rodgers.getHealth());
    assertEquals(false, rodgers.getIsCursed());
}

@Test()
public static void exceptionTest() throws Exception{
    rodgers = new Pirate("Dread Pirate Rodgers" , -100);

}

我知道我需要将预期 =(某种类型的异常)放在 test 的括号中,但我对异常类型一无所知。

4

4 回答 4

110

@Test(expected=Xyz.class)在 JUnit 4.7 中实际上有一个替代方法,使用RuleandExpectedException

在您的测试用例中,您声明一个ExpectedException带注释的@Rule,并为其分配一个默认值ExpectedException.none(). 然后在您期望异常的测试中,将该值替换为实际的期望值。这样做的好处是,无需使用丑陋的 try/catch 方法,您可以进一步指定异常中的消息是什么

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

@Test
public void myTest() {
    thrown.expect( Exception.class );
    thrown.expectMessage("Init Gold must be >= 0");

    rodgers = new Pirate("Dread Pirate Rodgers" , -100);
}

使用此方法,您可能能够测试通用异常中的消息是否是特定的。

添加 使用的另一个优点ExpectedException是您可以在测试用例的上下文中更精确地确定异常的范围。如果您只@Test(expected=Xyz.class)在测试中使用注解,那么 Xyz 异常可以在测试代码中的任何地方抛出——包括任何测试设置或测试方法中的预断言。这可能导致误报。

使用 ExpectedException,您可以推迟指定thrown.expect(Xyz.class)until 在任何设置和预断言之后,就在实际调用被测方法之前。因此,您可以更准确地确定由实际方法调用引发的异常,而不是任何测试夹具本身。

JUnit 5 注意:

JUnit 5 JUnit Jupiter 已完全删除@Test(expected=...)。它们被替换为 new ,这需要使用 Java 8 和 lambda 语法。 仍然可以通过 JUnit Vintage 在 JUnit 5 中使用。此外,JUnit Jupiter 也将通过使用junit-jupiter-migrationsupport 模块继续支持 JUnit 4 ,但前提是您添加了.@RuleExpectedExceptionassertThrows()ExpectedExceptionExpectedException@EnableRuleMigrationSupport

于 2013-05-23T23:02:07.417 回答
20

您可以在@Test注释中使用expected ,可以提供显式的 catch 块并在程序流程与预期不符时发出失败。

@Test(expected=Exception.class) // java.lang.Exception
public static void exceptionTest() throws Exception {
    rodgers = new Pirate("Dread Pirate Rodgers" , -100);
}

@Test
public static void exceptionTest() throws Exception {
    try {
        rodgers = new Pirate("Dread Pirate Rodgers" , -100);
        fail("should not reach this");
    } catch(Exception e) {
        // ok
    }
}

我个人的偏好是第一个解决方案。

于 2013-05-23T21:09:49.943 回答
9

您可以使用 JUnit 'expected' 来测试异常:

@Test(expected = ExceptionYouWishToTestFor.class)  
public void divisionWithException() {  
    // Test Code
}

之后,您可以在代码中抛出该特定异常。

于 2013-05-23T21:01:49.913 回答
7

Exception如果黄金不大于或等于零,我不会抛出。我会抛出一个IllegalArgumentException. 听起来你Pirate拥有负数的黄金当然是违法的。

public Pirate(String name, int initialGold) {
    if(initialGold < 0)
        throw new IllegalArgumentException("Init Gold must be >= 0");

然后在您的 JUnit 测试用例中,期待IllegalArgumentException.

@Test(expected=IllegalArgumentException.class)
public static void exceptionTest() {
于 2013-05-23T21:02:55.743 回答