如何将JUnit输出分配给String?

时间:2014-05-06 04:37:53

标签: java maven logging junit java-6

我想在单元测试失败时在我的问题跟踪软件中创建错误报告。这意味着当测试作为String失败时,我需要保存通常打印到IDE控制台的内容。到目前为止,我有以下代码:

@Rule
public ErrorCollector collector = new ErrorCollector();
...

@Test
public void testFailedUnitTest() {
    collector.checkThat(3, equalTo(5));
}

它将以下内容输出到控制台。我想将它放入一个String而不是/除了将它输出到我的IDE控制台之外:

java.lang.AssertionError: 
Expected: <5>
     but: was <3>
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
    at org.junit.Assert.assertThat(Assert.java:865)
    ...

我试过了:

  1. 使用try / catch块并使用e.get围绕它...但是 它没有捕获java.lang.AssertionError。 catch块中的代码甚至没有执行。我认为那是因为 我的收藏家正在等待抛出异常 testFailedUnitTest()完成以抛出错误,以便它可以 继续执行失败的测试。

  2. 使用try / catch块围绕正常的非收集器JUnit测试。

  3. 在所有测试完成后,抓住我的tearDown()中的输出 完成。但是没有像public String []这样的方法 the ErrorCollector JavaDoc中的getJUnitFailures()所以 那不起作用。

  4. 涉及在我的pom.xml中编辑某些内容的各种方法,例如setting the redirectTestOutputToFile element to true,但它们与2)具有相同的问题,遗憾的是一些遗留代码不使用Maven。但是,Maven特定的方法是可以接受的。

  5. 我与某人说过,我可能能够使用the Logger class将每个测试的输出记录到文件中,并以字符串形式读取每个文件。他承认这是一个草率的黑客,可能会干扰我们的其他伐木设施。

    这会不会起作用,如果是的话,这是最好的方法吗?

    提前谢谢你。 :)

1 个答案:

答案 0 :(得分:2)

看起来TestWatcher可以做你想做的事。


实施例

import java.io.PrintWriter;
import java.io.StringWriter;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;

public class FailedTestCapturer {

  @SuppressWarnings("null")
  private static int throwNPE() {
    String x = null;
    return x.length();
  }

  private String exception;
  @Rule
  public final TestRule watchman = new TestWatcher() {
    @Override
    protected void failed(Throwable e, Description description) {
      StringWriter writer = new StringWriter();
      e.printStackTrace(new PrintWriter(writer));
      exception = writer.toString();
      System.out.println("Captured exception! --> " + exception);
    }
  };

  @Test
  public void failingTest() {
    throwNPE();
  }
}

输出

Captured exception! --> java.lang.NullPointerException
    at FailedTestCapturer.throwNPE(FailedTestCapturer.java:15)
    at FailedTestCapturer.failingTest(FailedTestCapturer.java:32)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)