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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30822206/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 17:42:51  来源:igfitidea点击:

JUnit: Test exception doesn't work (AssertionError: Expected exception even if exception thrown)

javaexceptiontestingjunitassert

提问by asmb

I'm trying to test my class for a Exception. I've been trying a couple different methods, nothing works. What am I doing wrong here?

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

The class I'm trying to test, PrimeNumber.java:

我正在尝试测试的类 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;
    }

}

And now things I've tried to test:

现在我试图测试的东西:

With annotation

带注释

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

Results in failed test and:

测试失败的结果和:

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


With a JUnit rule:

使用 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();
}

Results in:

结果是:

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.access0(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.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access
// after the assignment to resultStr
throw e;
0(ParentRunner.java:58) at org.junit.runners.ParentRunner.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)


采纳答案by Dan Getz

Everything's working as it should. You've successfully been able to preventyour methods from throwing exceptions. You've successfully been able to test that they dothrow exceptions.

一切正常。您已经成功地阻止了您的方法抛出异常。您已经成功地测试了它们是否抛出异常。

It's just, it doesn't make sense to do both at the same time. You need to decideif you want each method to throw an exception or not when given wrong arguments.

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

If you dowant a method to throw an exception when given a wrong argument, then don't catch and handle the exception, just let it be thrown. Then, test that your method throws that exception, like you did above.

如果您确实希望某个方法在给定错误参数时抛出异常,则不要捕获和处理该异常,只需将其抛出即可。然后,测试您的方法是否抛出该异常,就像您在上面所做的那样。

If you don'twant the method to throw an exception when given a wrong argument, then decide what you want it to do instead. Then, test that your method does what you want it to. If it throws an exception, the test will fail.

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



That said, the way you handle numbers in your class doesn't make much sense. You're getting them as Strings, storing them as Strings, and returning them as Strings, but whenever you work with them, you convert them back and forth to ints. Why not just use inteverywhere in the first place?

也就是说,你在课堂上处理数字的方式没有多大意义。您将它们作为Strings获取,将它们存储为Strings,然后将它们作为Strings返回,但是无论何时使用它们,您都会将它们来回转换为ints。为什么不int首先在任何地方使用?

回答by Makoto

Your getPrimeResultis actually dealing with the exception as opposed to allowing it to propagate any further in the call stack. Hence, it's not being thrown, and the test will never be able to intercept it and assert against it (in that state).

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

While I think that this is a better approach, if you want to propagate it through the call stack, you would need to throwit after you've caught it.

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

##代码##