Unit Testing JSON Functions in Android

·

2 min read

Working with JSON is very common in Android apps. Parsing API responses, reading JSON files, creating JSON objects to send to a server are some examples of it. And like the good programmer you are, you likely want to write unit tests to test functions that handle JSON. But in doing so, you could run into a surprising and confusing problem. Let me elaborate.

Imagine we have a simple function that validates whether the given string is valid JSON.

class Validator {
    fun isStringValidJSON(string: String): Boolean {
        try {
            JSONObject(string)
        } catch (objEx: JSONException) {
            try {
                JSONArray(string)
            } catch (arrEx: JSONException) {
                return false
            }
        }
        return true
    }
}

JUnit 5 is used in these examples. To run unit tests written using JUnit 5, the following needs to be added to the build.gradle file.

tasks.withType(Test){
    useJUnitPlatform()
}

Then we have a unit test that verifies the logic of the above function. When an invalid JSON string is passed, it should return false. Ideally this unit test should pass.

internal class ValidatorTest {
    @Test
    fun jsonStringIsInvalid() {
        val validator = Validator()
        val string = "lorem ipsum"
        Assertions.assertFalse(validator.isStringValidJSON(string))
    }
}

But when the test is run, it fails!

What gives?!

The answer is in the Android Studio’s unit testing support docs under the “Method … not mocked.” section.

The android.jar file that is used to run unit tests does not contain any actual code — that is provided by the Android system image on real devices. Instead, all methods throw exceptions (by default). This is to make sure your unit tests only test your code and do not depend on any particular behaviour of the Android platform (that you have not explicitly mocked).

This basically means, the JSON in Java library (which contains the classes such as JSONObject and JSONArray) is a part of the Android SDK and it’s not available for unit testing by default. To resolve this, we have to add that library explicitly in the build.gradle file.

dependencies {
    ...
    testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1'
    testImplementation 'org.json:json:20220924'
}

Now when the test is run again, you should see it passing!


This is a tricky implementation detail that’s not very obvious and easy to find an answer to. Keep this in mind next time you write unit tests for JSON related functionalities.


The following video goes over this topic step by step and a bit more details. This written post is more of a summarized reference. Please watch the video it if you don’t fully understand how I arrive at certain points.