【问题标题】:wrong output for assert in junit test case for exceptions异常的junit测试用例中断言的错误输出
【发布时间】:2014-12-04 08:24:01
【问题描述】:
public class xyzException extends Exception{
    private final Object mSource;
    private final Object mObjectInError;
    private final Throwable mCause;

    public xyzException(Object obj1, Object obj2, Throwable cause, String message){
        super(message);
        this.mSource = obj1;
        this.mObjectInError = obj2;
        this.mCause = cause;
    }

    public static String getStackTrace(xyzException e) {
        StringWriter sw = new StringWriter();
        PrintWriter w = new PrintWriter(sw);
        e.printStackTrace(w);
        try {
            w.close();
        } 
        catch (final Exception ignore) {
        }
        return sw.toString();
    }

我已经在 junit 中为 getStackTrace() 方法编写了这个测试用例:

public class xyzExceptionTest {
        private String message;
        private String source;
        private xyzException obj;

        @Before
        public void setUp() throws Exception {
            message = "Exception";
            source = "source";
            obj = new xyzException(source, "MyObject.class", new NullPointerException(), message);
        }
        @Test
        public void getStackTraceTest() {
            assertEquals("GetStackTrace unexpected Value", "MyObject.class",xyzException.getStackTrace(obj));
        }
}

但这正在失败。我该如何纠正它以及它失败的原因? 错误是断言正在获取异常。 我应该如何避免这种情况。

【问题讨论】:

  • 用正确的方法编辑了 assertEquals..
  • 我明白了。这里的代码充满了“小错误”。例如,它不会编译,因为没有字段 mSource、mObjectInError 和 mCause。它们似乎微不足道,因为它们未被使用。应该使用它们吗?
  • 问题归结为您期望new NullPointerException().printStackTrace() 调用返回“MyObject.class”的原因。你到底想要达到什么目的?
  • 它正在正确编译,因为我刚刚放置了代码的主要部分。我将编辑并声明 mObject,mSource。我试图看看它在与异常一起使用时的行为。在 s.o.p 上,上述方法返回 MyObject.class。我想弄清楚,但它给出了不寻常的错误。
  • 您为什么期望 xyzException.getStackTrace 返回 mObjectInError?根据您的代码,它应该在传递的异常上返回对 printStackTrace 的调用。所有这一切都应该以 Throwable 类 Docu of Throwable 的 printStackTrace 调用结束,它的行为与您的预期完全不同

标签: java unit-testing exception junit exception-handling


【解决方案1】:

我稍微简化了您的代码,以向您展示没有什么特别之处。没有功能更改,我只删除了死代码。然后代码归结为:

public class XyzException extends Exception {

    public static String getStackTrace(XyzException e) {
        StringWriter sw = new StringWriter();
        try (PrintWriter w = new PrintWriter(sw)) {
            e.printStackTrace(w);
            return sw.toString();
        } 
    }

    public XyzException(String message) {
        super(message);
    }

}

和

public class XyzExceptionTest {
    private String message;
    private XyzException exception;

    @Before
    public void setUp() throws Exception {
        message = "A message";
        exception = new XyzException(message);
    }

    @Test
    public void getStackTraceTest() {
        System.out.println(XyzException.getStackTrace(obj));
        assertEquals("GetStackTrace unexpected Value", "MyObject.class", XyzException.getStackTrace(exception));
    }
}

现在,您可以看到XyzException 类现在什么都不是,它只是使用传递的message 调用父构造函数,没有别的。

静态getStackTrace(XyzException e) 方法也没有什么花哨的。它接受传递的异常并将其堆栈跟踪作为一个长字符串返回。在我的设置中,堆栈跟踪如下所示:

cz.slanec.playground.XyzException: A message
    at cz.slanec.playground.XyzExceptionTest.setUp(XyzExceptionTest.java:15)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    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.RunBefores.evaluate(RunBefores.java:24)
    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:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

您到底为什么希望"MyObject.class" 出现在其中的任何地方?该代码可以正常工作,请参见例如Throwable#printStackTrace().

从头开始,定义你的类和预期的行为,然后编写测试来验证所述行为。现在,测试完全错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-22
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-01
    • 2013-11-01
    相关资源
    最近更新 更多