JUnit:测试异常不起作用(AssertionError:即使抛出异常也会出现预期的异常)

时间:2015-06-13 18:35:36

标签: java exception testing junit assert

我试图测试我的课程是否有异常。我一直在尝试几种不同的方法,没有任何作用。我在这里做错了什么?

I级尝试测试,PrimeNumber.java:

public class PrimeNumber {

    static final Logger LOG = LogManager.getLogger("Log");

    private String primeNumberStr;

    public PrimeNumber(String primeNumberStr) {
        this.primeNumberStr = primeNumberStr;
    }

    public String getPrimeResult() {
        String resultStr = "";
        try {
            // Convert user input to int
            int primeNumberInt = Integer.parseInt(primeNumberStr);
            // Beginning of return message
            resultStr += primeNumberInt + " is ";
            // Add "not" if it's not a prime
            if (!Primes.isPrime(primeNumberInt))
                resultStr += "NOT ";
            // End return message
            resultStr += "a prime";
            // If not a valid number, catch
        } catch (NumberFormatException e) {
            // Log exception
            LOG.warn("NumberFormatException" + e.getMessage());
            // If empty user input
            if (primeNumberStr.length() == 0)
                resultStr += "No number inserted";
            // Else not empty but not valid
            else
                resultStr += primeNumberStr + " is not a valid number";
            resultStr += ". Only numbers without decimals are accepted.";
        }

        return resultStr;
    }

}

现在我试图测试的东西:

带注释

@Test(expected = NumberFormatException.class)
public void testNumberFormatExceptionBeingThrown() {
    PrimeNumber primeNumber = new PrimeNumber("6dg");
    primeNumber.getPrimeResult();
}

测试失败的结果:

java.lang.AssertionError: Expected exception: java.lang.Exception

使用JUnit规则:

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

@Test(expected = NumberFormatException.class)
public void testNumberFormatExceptionBeingThrown() {
    thrown.expect(NumberFormatException.class);
    thrown.expectMessage("For input string: \"a21\"");
    PrimeNumber primeNumber = new PrimeNumber("a21");
    primeNumber.getPrimeResult();
}

结果:

java.lang.AssertionError: Expected test to throw (an instance of java.lang.NumberFormatException and exception with message a string containing "For input string: \"a21\"")
at org.junit.Assert.fail(Assert.java:88)
at org.junit.rules.ExpectedException.failDueToMissingException(ExpectedException.java:263)
at org.junit.rules.ExpectedException.access$200(ExpectedException.java:106)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:245)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

2 个答案:

答案 0 :(得分:2)

一切都在发挥作用。您已成功地阻止您的方法抛出异常。您已成功测试他们执行抛出异常。

只是,同时做两者都没有意义。 如果您希望每个方法在给出错误参数时抛出异常,您需要决定

如果你想要一个方法在给出错误的参数时抛出异常,那么就不要捕获并处理异常,只是让它被抛出。然后,测试你的方法抛出异常,就像你上面那样。

如果你没有希望方法在给出错误的参数时抛出异常,那么决定你想要它做什么。然后,测试您的方法是否符合您的要求。如果它抛出异常,测试将失败。

那就是说,你在班上处理数字的方式没有多大意义。您将它们设为String s,将其存储为String s,并将其作为String s返回,但无论何时使用它们,都要将它们来回转换为{{ 1}}秒。为什么不首先在任何地方使用int

答案 1 :(得分:1)

您的getPrimeResult实际上是在处理异常,而不是允许它在调用堆栈中进一步传播。因此,它不会被抛出,并且测试将永远无法拦截它并对其进行断言(在该状态下)。

虽然我认为这是一种更好的方法,但是如果你想通过调用堆栈传播它,你需要在捕获它之后throw

// after the assignment to resultStr
throw e;