Reputation: 3211
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:
MockContext
, but since pretty much everything in AssetManager
is final
, I see no way to get the served the file I wantRenamingDelegatingContext
with a specific prefix, but the prefix doesn't work on asset files it seems...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:
junit_
to document that it is to be used by testing routines only (which is probably what I'll end up doing)but I still think that the original question might be of some interest, so any suggestion is welcome
Thank you!
Upvotes: 0
Views: 2561
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
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