I'm using the new Android Testing Support Library (com.android.support.test:runner:0.2
) to run Instrumentation Tests
(a.k.a Device or Emulator Tests).
I annotate my test class with @RunWith(AndroidJUnit4.class)
and use Android Studio to run them.
For my test cases I need a Context
instance. I can get it with InstrumentationRegistry
but it has two context related methods and it's not clear what the difference is.
What is the difference between InstrumentationRegistry.getContext()
vs. InstrumentationRegistry.getTargetContext()
?
I've found the answer here: https://code.google.com/p/android-test-kit/wiki/AndroidJUnitRunnerUserGuide
EDIT:
The documentation doesn't do a great job of explaining the differences so here it is from my POV:
You know that when you do instrumentation tests on Android then you have two apps:
So when you are writing your tests and you want to load a resource of your real app, use
getTargetContext()
.If you want to use a resource of your test app (e.g. a test input for one of your tests) then call
getContext()
.Took me hours to find that out.
A InstrumentedTest case had a context member which was set up in the setup like this:
this was used to open files, especially things like that:
Now I decided that I need to use some resource which is only available in the instrumented test, I did not want to distribute this resource with the release version. Therefore I recreated the resource directories under test:
But to be able to use this in code I had to call something like this:
Which would always fail because R.raw.v1 coincidently corresponded to something that was actually in my
R
resource file from the main application. By using resources in the instrumented tests, there were twoR
files generated. To fix that I had to include the test R file:the
resourceToUri
call would then however sill fail.The issue was, that I must not have used
InstrumentationRegistry.getTargetContext()
but ratherInstrumentationRegistry.getInstrumentation().getContext()
to get the resource ofR.raw.v1
so I blindly replace the setup of the context for the whole test class toIt worked well for the specific test but other tests in the test case started to fail with permission denied for the
filenameOriginal
I was using above.Turned out that by replacing the context to the instrumentation context I obtained a path to which my app had no access and I got
FileNotFoundException
withpermission denied
and noGrantTestRule
or other things would work.So be careful when using those contexts, it might screw your time :/
You may need
InstrumentationRegistry.getContext()
for access to raw resources of a test case.E.g., to access
app/src/androidTest/res/raw/resource_name.json
in a TestCase:final Context context = InstrumentationRegistry.getContext(); InputStream is = context.getResources().openRawResource(com.example.package.test.R.raw.resource_name);