JUnit 4 预期异常类型

2022-09-01 04:44:35

我正在尝试对其他人编写的代码进行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);

}

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


答案 1

实际上,在 JUnit 4.7 中使用 RuleExpectedException 的替代方法@Test(expected=Xyz.class)

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

@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);
}

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

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

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

JUnit 5 注意:

JUnit 5 JUnit Jupiter已经移除,并且完全移除。它们被替换为新的 assertThrows(),这需要使用 Java 8 和 lambda 语法。 仍然可用于 JUnit 5 到 JUnit Vintage。此外,JUnit Jupiter还将继续通过使用junit-jupiter-migrationsupport模块来支持JUnit 4,但前提是您添加@EnableRuleMigrationSupport的附加类级注释。@Test(expected=...)@RuleExpectedExceptionExpectedExceptionExpectedException


答案 2

您可以在@Test注释中使用预期也可以提供显式 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
    }
}

我个人更喜欢第一个解决方案。