我正在开发一个Android应用程序,其中我从web服务下载JSON数据。解析数据的类如下所示:
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;
}
}当我在我的应用程序中调用parseCourse()时,它可以很好地构建,但是当我试图在单元测试中测试这个方法时,我得到了这个异常:
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语言中是不可用的。
有没有办法修复这个问题,这样我就可以对解析JSON的类进行单元测试?
发布于 2015-04-17 04:03:09
您需要做的就是将以下行添加到build.gradle中的dependency部分:
testImplementation 'org.json:json:20180813'请注意,您还需要使用Android Studio 1.1或更高版本,并且至少需要构建工具版本22.0.0或更高版本才能工作!
testImplementation意味着依赖项被包含为测试依赖项,只有在编译项目以执行单元测试时才会使用。提供的jar不会包含在您的APK中,仅用于替换org.json包中缺少的类。
发布于 2010-10-20 04:42:30
编辑:查看末尾的更新答案
我找到了这个问题的答案。它不能解决我的问题,但至少它解释了为什么会有问题。
首先,我错误地假设JSONObject (从org.json包导入)是JRE的一部分。事实并非如此--在一个安卓项目中,它驻留在android.jar中(经典的"duh“时刻)。
这个发现增强了我的自信心。这可以通过在我的单元测试项目中添加对android.jar的引用来轻松解决--或者至少我是这么想的。这样做只会在运行测试时给我带来另一个错误:
java.lang.RuntimeException: Stub!
at org.json.JSONObject.<init>(JSONObject.java:8)
...至少这给了我更多的东西可以在谷歌上搜索。然而,我发现的并不是真正鼓舞人心的(又是一个经典的“废话”时刻)……
这个博客很好地描述了这个问题:Why Android isn’t ready for TDD, and how I tried anyway。如果你不厌其烦地阅读整篇文章,那么简单的解释如下:
这里的问题是,随SDK提供的android.jar在没有实现代码的情况下被清除。似乎可以预期的解决方案是,您应该在模拟器或真正的电话上运行您的单元测试。
考虑到这一点,当我在谷歌上进一步搜索时,我发现了一些关于这个问题的文章、博客和问题。我将在结尾处添加几个链接,供那些可能正在寻找的人使用:
如果你环顾四周,你会发现还有更多。
在这些链接中有一些关于Android中单元测试的建议/解决方案/替代方法,但我不会费心在此基础上做出一个好的答案(因为显然有太多关于Android开发的事情我还不知道)。如果有人有什么好的建议,我很乐意听到:)
更新:
在进行了更多的实验后,我实际上设法找到了这个特定问题的有效解决方案。我一开始没有尝试的原因是,我认为我在某个地方读到过,在我的Android应用程序中包含“普通”java库是有问题的。我尝试了很多不同的方法来解决我的问题,所以我想我也应该试一试--它真的起作用了!下面是如何实现的:
http://www.json.org/java/index.html
没有改变我的代码,没有改变我的测试,只是添加了这个库。一切都正常了,包括我的Android应用程序和单元测试。
我还在调试模式下测试了单步执行代码,在调试Android应用程序时,我的JsonCourseParser中的JSONObject是从Android SDK (android.jar)中获取的,但在调试我的单元测试时,它是从我自己的json.jar中获取的。我不确定这是否意味着在构建我的应用程序时没有包括json.jar,或者运行时是否智能地选择了要使用的正确的库。我也不确定这个额外的库是否会对我的最终应用程序产生任何其他影响。我想只有时间会告诉我们。
发布于 2015-06-04 02:36:04
我使用的是Björn Quentin的Unmock Gradle插件,它允许你用来自另一个android.jar (例如Robolectric)的真实版本替换默认android.jar中的存根类。
https://stackoverflow.com/questions/3951274
复制相似问题