解密注入大量 JUnit 的 Stack Trace

Deciphering Stack Trace that is infused with a lot of JUnit

请注意,这不是 this 的副本。


我一直在编写一些 运行 作为 JUnit 的代码。我阅读了上面链接的线程,它讨论了堆栈跟踪中错误的位置通常是如何最接近底部的。但是,因为我的代码被 运行 作为 JUnit 测试,所以堆栈跟踪中注入了很多我认为是代码被 运行 作为单元测试的结果,所以错误不能直接追溯到堆栈跟踪的底部,就像上面的post所说的(<--为什么'重复)。

以下是我在 运行ning 代码后得到的堆栈跟踪。

java.lang.NullPointerException
    at API.ItemFetcher.<init>(ItemFetcher.java:39)
    at API.MarketConstants.<clinit>(MarketConstants.java:24)
    at API.ItemFetcher.setOtherMonetaryValues(ItemFetcher.java:153)
    at API.ItemFetcher.<init>(ItemFetcher.java:53)
    at Tests.Tests.test(Tests.java:14)
    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:497)
    at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    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[=10=]0(ParentRunner.java:58)
    at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    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)

我的代码结构如下

-src
  -API
    -Item.java
    -ItemFetcher.java
    -MarketConstants.java
    -IrrelevantFolder
  -Tests
    -Tests.java

根据堆栈跟踪,我应该在代码中的何处查找错误?由于所有的 JUnit 内容,我不是 100% 确定要查找的位置在堆栈跟踪中。就像我之前说的,我已经阅读了其他关于此的 SO 线程,但之前没有涉及它。

如果您查看堆栈跟踪中的根本原因,它指出 NullPointerException 发生 at API.ItemFetcher.<init>(ItemFetcher.java:39)。这意味着在第 39 行,在 ItemFetcher class 内,发生了 NullPointerException

请记住,JUnit 只是调用您现有的 classes/methods。因此,请始终查找您的代码在堆栈跟踪中的位置。

堆栈跟踪是一个强大的工具,您引用的 post 提供了关于如何使用它的非常好的建议。

但是堆栈跟踪是 ONLY 一个 "tool"。 必须完成这项工作。你必须逻辑思考

不能说"line 'ItemFetcher.java:xyz' always used to work, so it can't possibly be the problem"这样的废话。那是我否决你的时候;)你删除了那句话(谢谢!),我收回了我的否决票。

以下是我解决问题的方法:

  1. 是的,您的回溯中有很多 "JUnit" 内容。

    问:JUnit 是如何导致问题的?

    答:可能不能。就像 RamV13(正确!)指出的那样,"Keep in mind that JUnit just calls YOUR existing classes/methods. So always look for where your code is in the stack trace".

    因此,对于初学者,我会在代码中的其他地方 查找,并简单地忽略 JUnit 行。

  2. 正如 RamV13 还指出的那样,"ItemFetcher.java:39" 是 "your code" 的起点。这绝对是开始寻找的好地方。

  3. 问:你在找什么?

    答:如果你有一个 "DivideByZero" 错误,你会寻找一个计算结果可能为“0”分母的算术表达式。如果你有 IOException",你会寻找 "open()"、"read()" 或 "write()".

    在这种情况下,您有一个 "NullPointerException"。

    所以你在寻找一个未初始化的变量

  4. 问:什么变量?

最好看的地方是 发生 NullPointerException 的确切行:

java.lang.NullPointerException
    at API.ItemFetcher.<init>(ItemFetcher.java:39) 
    <-- Your problem is an uninitialized variable at line 39!
  1. 问:为什么没有初始化?

那是你自己想出来的。回顾代码(甚至可能回溯到 ItemFetcher.java:39),看看它 应该 被初始化的地方。

然后修复它:)

'希望对您有所帮助!