How to unit test JSON parsing

后端 未结 5 1342
北恋
北恋 2020-12-08 00:57

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         


        
相关标签:
5条回答
  • 2020-12-08 01:32

    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.

    0 讨论(0)
  • 2020-12-08 01:34

    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:

    • android.jar In The SDK Only Has The API And Not The Implementation?
    • Can I use android.os.* libraries in a standalone project?
    • AndroidTesting
    • Eclipse + Android + JUnit test references android.os class = NoClassDefFoundError (not sure why on earth I didn't find this one when I initially wrote my question, I must have been completely lost...)

    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:

    • I downloaded the source for the "real" org.json package from here: http://www.json.org/java/index.html
    • Next I compiled the source code and packed it together in my own json.jar
    • I added the newly created json.jar to the build path of my project (the main project of my Android application, not the test project)

    No 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...

    0 讨论(0)
  • 2020-12-08 01:44

    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:

    1. Download org.json's json.jar from here (or wherever): http://mvnrepository.com/artifact/org.json/json
    2. Add a folder 'libs-test' to your project, copy the json.jar file to it
    3. In Eclipse open: Run / Run Configurations, select JUnit / YourTestClass
    4. On the Classpath tab, remove "Google APIs" from Bootstrap entries
    5. Click "Add JARs", navigate to /libs-test/json.jar and add it.
    6. Click "Close"
    7. Run your tests
    0 讨论(0)
  • 2020-12-08 01:54

    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.

    0 讨论(0)
  • 2020-12-08 01:54

    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).

    0 讨论(0)
提交回复
热议问题