Rick77
Rick77

Reputation: 3211

Mock access to /asset files

I'm trying to create a test unit for a class accessing a file in /asset and, as far as I have experimented, I see no way do that without altering the logic of the class being tested.

What I would like to accomplish is the creation of an environment where I can point my class to the asset file I like (and not the one originally pointed in the code), so that I can run multiple tests with it, so for example, if my original code looks something like:

ctx.getAssets().open("config.txt")

i can instead open

bogus_config.txt
ok_config.txt
nonexisting_config.txt

So far I have tried:

Is there a better way (some Java Magik Reflection Trick(Tm) of sorts, for instance) to achieve what I want?

Even though I'm very new to unit testing in general, I know that I could pick any of the following work-around solutions:

but I still think that the original question might be of some interest, so any suggestion is welcome

Thank you!

Upvotes: 0

Views: 2561

Answers (2)

Rasoul Miri
Rasoul Miri

Reputation: 12222

you can use this way

class AssetsUtils {

    companion object {

        fun <T> loadResponse(
            path: String,
            tClass: Class<T>?,
            isPrettyPrinting: Boolean? = false,
            isUnitTest: Boolean? = true
        ): T {

            val json = File(
                "src/${if (isUnitTest == true) {
                    "test"
                } else {
                    "androidTest"
                }}/assets/${path}"
            ).bufferedReader().use {
                it.readText()
            }

            val gson = GsonBuilder()
                .serializeNulls()
                .setPrettyPrinting()
                .create()

            val model = gson.fromJson(json, tClass)

            if (isPrettyPrinting == true) {
                println("Load Response ------------------------------------------------------------------------------------------------")
                println()
                println("Response file: $path")
                println(gson.toJson(model))
                println()
                println("Model: $model")
                println()
                println("--------------------------------------------------------------------------------------------------------------")
            }

            return model
        }
    }
}

example: the file in "C://ProjectA/app/src/test/asstes/mockApi/folder1/user.json"

AssetsUtils.loadResponse(
       "mockApi/folder1/user.json",
       UserModel::class.java
)

Upvotes: 0

k3b
k3b

Reputation: 14755

  > I see no way do that without altering the logic of the class being tested.

I agree but the change would be quite minimal: move the code ctx.getAssets().open("config.txt") into a protected method InputStream openConfig(Context ctx) which you can easily overide/fake/mock in your tests. If you use Eclipse or Androidstudio mark the statement and execute context-menu Refactor/Extract-Method.

Upvotes: 1

Related Questions