I\'m working on an Android app in which I download JSON data from a web service. The class parsing the data looks something like this:
public class JsonCours
I had the same problem but I found a better way. The framework Roboelectric does the job. At first I just added the roboelectric.jar as external library (because I don't use Maven) to the build path of my Java JUnit test project and as "class annotation" I added @RunWith(RobolectricTestRunner.class)
. But then I got a NoClassDefFoundError: android/net/Uri. After I still added the android.jar itself used by the corresponding Android project (although the Android library with its android.jar was already a part of my build path), it works.
Edit: see updated answer at the end
I've found the answer to this one. It doesn't solve my problem, but at least it explains why there is a problem.
First, I made the faulty assumption that the JSONObject
(imported from the org.json
package) was included as a part of the JRE. It isn't - in an Android project, this resides in android.jar
(classic "duh" moment).
This discovery boosted my self confidence a bit. This could easily be solved by adding a reference to the android.jar
in my unit test project - or at least so I thought for a brief moment. Doing so only gave me another error when running my test:
java.lang.RuntimeException: Stub!
at org.json.JSONObject.<init>(JSONObject.java:8)
...
At least this gave me something more to google for. What I found however, wasn't really encouraging (yet another classic "duh" moment)...
This blog describes the problem pretty well: Why Android isn’t ready for TDD, and how I tried anyway. If you don't bother to read the whole thing, the brief explanation is as follows:
The problem here is that the android.jar supplied with the SDK is stubbed out with no implementation code. The solution that seems to be expected is that you should run your unit tests on the emulator or a real phone.
When further doing some googling with this in mind, I found several articles, blogs and also questions here on SO regarding the issue. I'll add a few links here at the end, for those that might be looking:
And there are plenty more if you look around.
There are several suggestions/solution/alternative approaches to unit testing in Android in many of those links, but I won't bother to try to make a good answer based on that (as there is obviously way too much I still don't know about Android development). If anybody has any nice tips though, I'll be glad to hear about them :)
UPDATE:
After experimenting a bit more, I actually managed to find a working solution to this specific problem. The reason why I didn't try this in the first place, was that I thought I had read somewhere that it would be problematic to include "normal" java libraries in my Android app. I was trying so many different things to get around my problem, so I thought I'd just give this a try as well - and it actually worked! Here is how:
org.json
package from here: http://www.json.org/java/index.htmlNo changes to my code, no changes to my test, only adding this library. And everything works, both my Android app and my unit tests.
I also tested stepping through the code in debug mode, and when debugging the Android app the JSONObject
in my JsonCourseParser
is fetched from the Android SDK (android.jar), but when debugging my unit test it is fetched from my own json.jar. Not sure if this means that the json.jar isn't included when my app is built, or if the runtime intelligently selects the correct library to use. Also not sure if this extra library might have any other effects on my final app. I guess only time will tell...
I had this exact problem in my JSON tests. Your updated answer led me to try a simpler approach, which worked for my project. It allows me to run JUnit tests, using the 'real' org.json JAR, on my non-Android classes from within Eclipse:
All you need to do is add the following line to the dependency section in your build.gradle:
testImplementation 'org.json:json:20140107'
Note that you also need to use Android Studio 1.1 or higher and at least build tools version 22.0.0 or above for this to work!
testImplementation
means that the dependency is included as a test dependency will only be used when your project is being compiled for executing unit tests. The supplied jar will not be included in your APK and will only be used to replace the missing classes in the org.json
package.
I'm using Björn Quentin's Unmock Gradle plugin, which allows you to replace stubbed classes in the default android.jar with real versions from another android.jar (e.g. Robolectric).