如何unit testingJSONparsing

我正在从Android Web应用程序中下载JSON数据。 parsing数据的类看起来像这样:

public class JsonCourseParser implements CourseParser { public Course parseCourse(String courseData) { Course result; try { JSONObject jsonObject = new JSONObject(courseData); ... result = new Course("foo", "bar"); } catch (JSONException e) { result = null; } return result; } } 

这build立得很好,它适用于我从我的应用程序中调用parseCourse() ,但是当我尝试在unit testing中testing此方法时,我得到此exception:

 java.lang.NoClassDefFoundError: org/json/JSONException at JsonCourseParserTest.initClass(JsonCourseParserTest.java:15) 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:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49) 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) Caused by: java.lang.ClassNotFoundException: org.json.JSONException at java.net.URLClassLoader$1.run(URLClassLoader.java:202) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:248) ... 16 more 

看起来,Android Framework附带的org.json包的类在默认情况下不能在Java中使用。

有没有办法可以解决这个问题,我可以unit testingparsingJSON的类?

Solutions Collecting From Web of "如何unit testingJSONparsing"

所有你需要做的是将下面的行添加到build.gradle中的依赖项部分:

 testCompile 'org.json:json:20140107' 

请注意,您还需要使用Android Studio 1.1或更高版本,并且至less需要构build工具版本22.0.0或更高版本才能使用!

testCompile意味着依赖被包含在testing依赖中,只有当你的项目被编译执行unit testing时才会使用。 提供的jar不会被包含在你的APK中,只会用来replaceorg.json包中缺less的类。

编辑:在最后看到更新的答案

我find了这个答案。 它不能解决我的问题,但至less可以解释为什么有问题。

首先,我做了错误的假设,即将JSONObject (从org.json包导入)作为JRE的一部分。 它不是 – 在一个Android项目中,这个驻留在android.jar (经典的“杜”时刻)。

这个发现提升了我的自信心。 这可以很容易地通过在我的unit testing项目中添加对android.jar的引用来解决 – 或者至less是我想了一会儿。 这样做只会在运行我的testing时给我另一个错误:

 java.lang.RuntimeException: Stub! at org.json.JSONObject.<init>(JSONObject.java:8) ... 

至less这给了我更多的谷歌。 然而,我发现并不是真的令人鼓舞(又一个经典的“唔”时刻)…

这个博客很好地描述了这个问题: 为什么Android还没有准备好TDD,以及我怎么尝试 。 如果你不去理解整个事情,简单的解释如下:

这里的问题是,随SDK提供的android.jar被删除,没有实现代码。 似乎预期的解决scheme是,你应该在模拟器或真正的手机上运行你的unit testing。

当进一步做一些search时,我发现了几篇关于这个问题的文章,博客和关于SO的问题。 最后我会在这里添加一些链接,对于那些可能正在寻找的链接:

  • android.jar在SDK中只有API而不是执行?
  • 我可以在独立的项目中使用android.os。*库吗?
  • AndroidTesting
  • Eclipse + Android + JUnittesting引用android.os class = NoClassDefFoundError (不知道为什么在我最初写下我的问题时我没有find这个,我一定已经完全失去了…)

如果你环顾四周,还有更多。

有很多build议/解决scheme/替代方法在Android的unit testing中的许多链接,但我不打算尝试做出一个很好的答案基于此(因为显然太多,我还不知道关于Android开发)。 如果有人有任何好的提示,但我会很高兴听到他们:)

更新:
实验了一下之后,我实际上设法find了解决这个特定问题的方法。 我之所以没有尝试这个,是因为我曾经在某处读过,在我的Android应用程序中包含“正常”的java库会有问题。 我尝试了很多不同的东西来解决我的问题,所以我想我也试试这个,实际上它工作正常! 这里是如何:

  • 我从这里下载了“真正的” org.json包的源代码: http : //www.json.org/java/index.html
  • 接下来我编译了源代码,并把它们放在我自己的json.jar中
  • 我将新创build的json.jar添加到我的项目的构buildpath(我的Android应用程序的主项目,而不是testing项目)

没有改变我的代码,没有改变我的testing,只添加这个库。 一切正常,我的Android应用程序和我的unit testing。

我也在debugging模式下testing了代码,在debuggingAndroid应用程序时,我的JsonCourseParserJSONObject是从Android SDK( android.jar )中获取的,但是在debugging我的unit testing时,它是从我自己的json.jar中获取的 。 不知道这是否意味着我的应用程序构build时不包含json.jar ,或者如果运行时智能地select了正确的库来使用。 也不知道这个额外的库是否可能对我的最终应用程序有任何其他影响。 我想只有时间会告诉…

我正在使用BjörnQuentin的Unmock Gradle插件,它允许用默认android.jar中的stubbed类replace另一个android.jar(例如Robolectric)的实际版本。

我有同样的问题,但我find了一个更好的办法。 框架Roboelectric做这项工作。 起初,我只是将roboelectric.jar作为外部库(因为我没有使用Maven)添加到我的Java JUnittesting项目的构buildpath中,并添加了@RunWith(RobolectricTestRunner.class)作为“类注解”。 但后来我得到了一个NoClassDefFoundError:android /净/ Uri 。 在我还添加了相应的Android项目使用的android.jar之后(虽然android.jar的Android库已经是我的构buildpath的一部分),但是它工作正常。

我在我的JSONtesting中有这个确切的问题。 你的更新的答案让我尝试一个更简单的方法,这为我的项目工作。 它允许我在Eclipse的非Android类上使用真正的org.json JAR运行JUnittesting:

  1. 从这里(或任何地方)下载org.json的json.jar: http ://mvnrepository.com/artifact/org.json/json
  2. 将libs-test文件夹添加到项目中,将json.jar文件复制到该文件夹​​中
  3. 在Eclipse打开:运行/运行configuration,selectJUnit / YourTestClass
  4. 在类path选项卡上,从引导条目中删除“Google API”
  5. 点击“添加JAR”,导航到/libs-test/json.jar并添加它。
  6. 点击“closures”
  7. 运行你的testing