简体   繁体   English

在Junit中测试异常时忽略堆栈跟踪

[英]Ignoring stacktrace when testing for exceptions in Junit

We are testing for exceptions in our unit tests 我们正在测试单元测试中的异常

@Test(expected=IOException.class)
     public void test() {
     // run some code that throws IOException.
}

The test is passing but as a part of the maven build that runs the test, the stacktrace comes in the console output. 测试正在通过,但作为运行测试的maven构建的一部分,stacktrace进入控制台输出。 Is there anyway in which this stacktrace can be ignored in the tests. 无论如何,在测试中可以忽略此堆栈跟踪。

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.7.1</version>
    <configuration>
        <redirectTestOutputToFile>true</redirectTestOutputToFile>
    </configuration>
</plugin>

Place the above code into your pom.xml's plugins section. 将上面的代码放入pom.xml的插件部分。 redirectTestOutputToFile will remove the stacktrace from the console output. redirectTestOutputToFile将从控制台输出中删除堆栈跟踪。 Obviously, replace the version of surfire with the version you are using. 显然,用你正在使用的版本替换surfire版本。

BTW the redirectTestOutputToFile parameter is available in the failsafe plugin as well, so you can apply this to your integration tests in the same fashion. BTW redirectTestOutputToFile参数也可以在failsafe插件中使用,因此您可以以相同的方式将其应用于集成测试。

There isn't a nice way to do this, and it's not worth it anyway. 没有一种很好的方法可以做到这一点,无论如何它都是不值得的。 I assume that the printed stacktrace is coming from the called code, and not from your test code: 我假设打印的堆栈跟踪来自被调用的代码,而不是来自您的测试代码:

public class ExpectedExceptionTest {
  @Test(expected = IOException.class)
  public void test() throws Exception {
    foobar();
  }

  public void foobar() throws IOException {
    try {
      throw new IOException();
    } catch (IOException e) {
      e.printStackTrace(System.err);
      throw e;
    }
  }
}

Here, the stacktrace which appears in the maven build log is coming from the error handling of the method that you're trying to test. 这里,maven构建日志中出现的堆栈跟踪来自您尝试测试的方法的错误处理。 You don't want to change this error handling. 您不想更改此错误处理。 If the test fails, then you want to know what's happened. 如果测试失败,那么你想知道发生了什么。

If you change it, then it also complicates the code under test unnecessarily. 如果你改变它,那么它也会使不必要的测试代码复杂化。 Apart from this specific test, you always want the stacktrace to appear. 除了这个特定的测试,你总是希望出现堆栈跟踪。

So, can we set System.err to be null, as was suggested elsewhere? 那么,我们可以将System.err设置为null,如其他地方所建议的那样吗? No. If you call 不,如果你打电话

System.setErr(null);

Then this will result in a NullPointerException (with the above error handling). 然后这将导致NullPointerException (具有上述错误处理)。

If you use log4j or similar for your logging, then you can have a @Rule which temporarily sets the logging level to INFO so that the exception doesn't appear in your logs. 如果您使用log4j或类似日志进行日志记录,则可以使用@Rule临时将日志记录级别设置为INFO,以便日志中不会显示该异常。 Again, the debug won't appear when you need it most, if the test fails. 同样,如果测试失败,调试将不会在您最需要时出现。

I get these exception stacktraces all of the time in my project build output(s). 我在项目构建输出中一直得到这些异常堆栈跟踪。 I just accept it and congratulate myself that I'm testing error conditions correctly :-) 我接受它并祝贺自己正确测试错误情况:-)

System.err is what that gets printed to, and it is a PrintStream which can be modified at runtime. System.err是打印到的,它是一个可以在运行时修改的PrintStream。 So in the System.err, put a new PrintStream made from an OutputStream that prints out nothing when write(int i) is called: 因此,在System.err中,放置一个由OutputStream创建的新PrintStream,在调用write(int i)时不打印任何内容:

System.setErr(new PrintStream(new OutputStream(){public void write(int i){}}));

Remember to backup the current PrintStream in System.err though after you're done suppressing output, or else you won't receive other errors that might actually be useful to know about. 记住在完成抑制输出后备份System.err中的当前PrintStream,否则您将不会收到其他可能实际有用的错误。

You can backup and set the fake on in BeforeClass and restore in AfterClass or something like that. 您可以在BeforeClass中备份和设置伪造,并在AfterClass或类似的东西中恢复。


Additional notes: 补充说明:

Here's a fuller set of lines you can put in your test: 这里有一套更完整的线条供您测试:

java.io.PrintStream realErrorStream = System.err;
System.setErr(new java.io.PrintStream(new java.io.OutputStream(){public void write(int i){}}));
...
System.setErr(realErrorStream);

y solution to assert that I actually catch expected Exception without seeing stacktrace is 解决方案断言我实际上没有看到堆栈跟踪就抓住了预期的异常

@Test
public void test() {
    try {
 // run some code that throws IOException.
    } catch (Exception ex) {
        assertTrue(ex.getClass().equals(IOException.class));
    }
}

One of the things that you can do, is not to use expected exception feature. 您可以做的一件事是不使用预期的异常功能。 Sometimes I do this, when there are just too many tests, and I do not want a real exception to get ignored because the maven build has printed expected expectations. 有时我这样做,当测试太多时,我不希望真正的异常被忽略,因为maven构建已经打印出预期的期望值。

boolean exceptionOccured = false;
try {
    // My test here);
} catch (ExpectedException ex) {
   exceptionOccured = true;
}
if(!exceptionOccured) {
    Asser.fail();
}

In my case, I am doing an assertNotNull with Thrown exception in the catch block. 在我的例子中,我在catch块中执行了一个带有Thrown异常的assertNotNull。 This way if the reverse happened in the code I will get assertNotNull Failure. 这样如果在代码中发生相反的情况,我将得到assertNotNull Failure。 And Yes There is nothing to hate about if stacktrace is printed. 是的如果打印了stacktrace,没有什么可恨的。 It has a reason. 这是有原因的。

//Building the precondition for test case goes here.
try {
    begin();       
    System.out.println("Expected ConstraintViolationException occurred");
    dao.save(myObject);            
    commit();
} catch (Exception e){
    assertNotNull(e);
} finally {
    rollback();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM