Java JUnit4应为异常类型

Java JUnit4应为异常类型,java,object,testing,junit,Java,Object,Testing,Junit,我正在尝试对其他人编写的代码进行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;

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

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

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

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

在此之后,由您在代码中抛出特定异常。

如果黄金不大于或等于零,我不会抛出
异常。我会抛出一个
非法argumentException
。听起来你的
海盗
拥有负数量的黄金肯定是违法的

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

您可以在@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
    }
}

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

在JUnit4.7中,除了使用和

在您的测试用例中,您声明一个用
@Rule
注释的
ExpectedException
,并为其指定一个默认值
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,您可以推迟指定抛出的
expect(Xyz.class)
,直到任何设置和预断言之后,即实际调用测试中的方法之前。因此,您可以更准确地确定由实际方法调用而不是任何测试装置本身引发的异常的范围

JUnit 5注意:


JUnit 5 JUnit Jupiter已经删除了
@Test(预期=…)
@Rule
ExpectedException
。它们被替换为新的,这需要使用Java8和lambda语法<代码>ExpectedException
仍然可以在JUnit5到JUnitVintage中使用。此外,JUnit Jupiter还将通过使用继续支持JUnit 4
ExpectedException
,但前提是您添加了的附加类级注释。

运行测试并查看发生了什么。您正在编写测试:您希望验证是否引发了特定类型的异常。目前您实际上正在抛出
异常
,但这是一个错误的选择-它可能应该是
IllegalArgumentException
。无论哪种方式,您的测试基本上都需要检查是否抛出了正确的异常-但这取决于您决定该类型。为什么rodgers是一个类字段?测试中的代码正在抛出异常-这是您应该在预期的=。。。。。条款(Exception实际上是java.lang.Exception)我肯定会对此感到遗憾,但是海盗类应该为任何不叫“ROBERTS”的“恐怖”海盗提出一个“Wannable”例外是的,是的-继续往下修改我:-)虽然我同意这是更好的实现,我根本不应该改变海盗类。如果你不能改变
海盗
构造函数抛出
异常
,那么你只能接受
@Test(expected=Exception.class)
。向它添加.class可以使它正常工作并正常测试,thanksThrows一个
异常
不是一个好的做法。您应该使异常更有意义。+1,因为当您使用
@test(expected=IllegalArgumentException.class)
时,您不知道测试中的哪一行会引发异常。因此,如果错误的行引发异常,测试将通过,但您的代码可能存在潜在问题。@Rule ExpectedException的另一个巨大优势是@Rule ExpectedException。别忘了ExpectedException必须声明为公共。
@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
    }
}
@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);
}