JUnit 4预期的异常类型

Mar*_*rus 34 java testing junit object

我正在尝试对其他人编写的代码进行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;
}
Run Code Online (Sandbox Code Playgroud)

我的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);

}
Run Code Online (Sandbox Code Playgroud)

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

Kev*_*ker 106

实际上有一个替代@Test(expected=Xyz.class)JUnit 4.7使用RuleExpectedException

在您的测试用例中,您声明带有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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

JUnit 5注意:

JUnit 5 JUnit Jupiter已经删除了@Test(expected=...),@Rule并且ExpectedException完全删除了.它们被new替换assertThrows(),需要使用Java 8和lambda语法. ExpectedException仍然可以在JUnit 5到JUnit Vintage中使用.此外,JUnit Jupiter还将继续ExpectedException通过使用junit-jupiter-migrationsupport模块来支持JUnit 4 ,但前提是您添加了一个额外的类级别注释@EnableRuleMigrationSupport.

  • +1,因为当你使用`@Test(expected = IllegalArgumentException.class)`时,你不确切地知道测试中哪一行抛出了异常.因此,如果错误的行抛出异常,测试将通过,但您的代码可能存在潜在问题. (20认同)

Ste*_* Oh 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
    }
}
Run Code Online (Sandbox Code Playgroud)

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


Mic*_*l W 9

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

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

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


rge*_*man 7

Exception如果黄金不大于或等于零,我不会抛出.我会抛出一个IllegalArgumentException.当然Pirate,拥有负金量肯定是违法的.

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

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

@Test(expected=IllegalArgumentException.class)
public static void exceptionTest() {
Run Code Online (Sandbox Code Playgroud)