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
JUnit: Test exception doesn't work (AssertionError: Expected exception even if exception thrown)
提问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 String
s, storing them as String
s, and returning them as String
s, but whenever you work with them, you convert them back and forth to int
s. Why not just use int
everywhere in the first place?
也就是说,你在课堂上处理数字的方式没有多大意义。您将它们作为String
s获取,将它们存储为String
s,然后将它们作为String
s返回,但是无论何时使用它们,您都会将它们来回转换为int
s。为什么不int
首先在任何地方使用?
回答by Makoto
Your getPrimeResult
is 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 throw
it after you've caught it.
虽然我认为这是一种更好的方法,但如果您想通过调用堆栈传播它,则需要throw
在捕获它后使用它。