[英]What's the difference between getTargetContext() and getContext (on InstrumentationRegistry)?
I'm using the new Android Testing Support Library ( com.android.support.test:runner:0.2
) to run Instrumentation Tests (aka Device or Emulator Tests). 我正在使用新的Android测试支持库( com.android.support.test:runner:0.2
)来运行Instrumentation Tests(aka Device或Emulator Tests)。
I annotate my test class with @RunWith(AndroidJUnit4.class)
and use Android Studio to run them. 我使用@RunWith(AndroidJUnit4.class)
注释我的测试类,并使用Android Studio来运行它们。
For my test cases I need a Context
instance. 对于我的测试用例,我需要一个Context
实例。 I can get it with InstrumentationRegistry
but it has two context related methods and it's not clear what the difference is. 我可以通过InstrumentationRegistry
获得它,但它有两个与上下文相关的方法,并不清楚它们之间的区别。
What is the difference between InstrumentationRegistry.getContext()
vs. InstrumentationRegistry.getTargetContext()
? InstrumentationRegistry.getContext()
与InstrumentationRegistry.getTargetContext()
什么区别?
InstrumentationRegistry
is an exposed registry instance that holds a reference to the instrumentation running in the process and it's arguments and allows injection of the following instances:InstrumentationRegistry
是一个公开的注册表实例,它包含对进程中运行的检测的引用及其参数,并允许注入以下实例:
InstrumentationRegistry.getInstrumentation()
, returns the Instrumentation currently running.InstrumentationRegistry.getInstrumentation()
返回当前正在运行的Instrumentation。InstrumentationRegistry.getContext()
, returns the Context of this Instrumentation's package.InstrumentationRegistry.getContext()
返回此Instrumentation包的Context。InstrumentationRegistry.getTargetContext()
, returns the application Context of the target application.InstrumentationRegistry.getTargetContext()
,返回目标应用程序的应用程序上下文。InstrumentationRegistry.getArguments()
, returns a copy of arguments Bundle that was passed to this Instrumentation.InstrumentationRegistry.getArguments()
返回传递给此Instrumentation的参数Bundle的副本。 This is useful when you want to access the command line arguments passed to Instrumentation for your test. 当您想要访问为测试传递给Instrumentation的命令行参数时,这非常有用。
EDIT: 编辑:
So when to use getContext() vs getTargetContext()? 那么何时使用getContext()vs getTargetContext()?
The documentation doesn't do a great job of explaining the differences so here it is from my POV: 文档在解释差异方面做得不是很好,所以这里来自我的POV:
You know that when you do instrumentation tests on Android then you have two apps: 您知道,当您在Android上进行仪器测试时,您有两个应用程序:
So when you are writing your tests and you want to load a resource of your real app , use getTargetContext()
. 因此,当您编写测试并希望加载真实应用程序的资源时,请使用getTargetContext()
。
If you want to use a resource of your test app (eg a test input for one of your tests) then call getContext()
. 如果您想使用测试应用程序的资源(例如,您的某个测试的测试输入),请调用getContext()
。
You may need InstrumentationRegistry.getContext()
for access to raw resources of a test case. 您可能需要InstrumentationRegistry.getContext()
来访问测试用例的原始资源。
Eg, to access app/src/androidTest/res/raw/resource_name.json
in a TestCase: 例如,要在TestCase中访问app/src/androidTest/res/raw/resource_name.json
:
final Context context = InstrumentationRegistry.getContext(); InputStream is = context.getResources().openRawResource(com.example.package.test.R.raw.resource_name);
Took me hours to find that out. 花了我几个小时才找到它。
A InstrumentedTest case had a context member which was set up in the setup like this: InstrumentedTest案例有一个上下文成员,它在设置中设置如下:
context = InstrumentationRegistry.getTargetContext();
this was used to open files, especially things like that: 这用于打开文件,尤其是这样的东西:
String filenameOriginal = context.getCacheDir() + "/initial.csv";
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: 因此,我重新创建了测试中的资源目录:
app\src\androidTest
└───res
└───raw
v1.csv
But to be able to use this in code I had to call something like this: 但是为了能够在代码中使用它,我不得不调用这样的东西:
public static Uri resourceToUri(Context context, int resID)
{
return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
context.getResources().getResourcePackageName(resID) + '/' +
context.getResources().getResourceTypeName(resID) + '/' +
context.getResources().getResourceEntryName(resID));
}
resourceToUri(context, R.raw.v1)
Which would always fail because R.raw.v1 coincidently corresponded to something that was actually in my R
resource file from the main application. 这总是会失败,因为R.raw.v1恰好与主应用程序中我的R
资源文件中的内容相对应。 By using resources in the instrumented tests, there were two R
files generated. 通过使用检测测试中的资源,生成了两个R
文件。 To fix that I had to include the test R file: 要解决这个问题,我必须包含测试R文件:
import com.my_thing.app.my_app.test.R;
the resourceToUri
call would then however sill fail. 然后, resourceToUri
调用将失败。
The issue was, that I must not have used InstrumentationRegistry.getTargetContext()
but rather InstrumentationRegistry.getInstrumentation().getContext()
to get the resource of R.raw.v1
so I blindly replace the setup of the context for the whole test class to 问题是,我不能使用InstrumentationRegistry.getTargetContext()
而是使用InstrumentationRegistry.getInstrumentation().getContext()
来获取R.raw.v1
的资源,所以我盲目地替换整个测试类的上下文设置至
context = InstrumentationRegistry.getInstrumentation().getContext();
It 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. 它适用于特定测试,但测试用例中的其他测试开始失败,并且我在上面使用的filenameOriginal
被拒绝了。
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
with permission denied
and no GrantTestRule
or other things would work. 事实证明,通过将上下文替换为检测上下文,我获得了一个我的应用程序无法访问的路径,并且我获得了FileNotFoundException
且permission denied
并且没有GrantTestRule
或其他东西可以工作。
So be careful when using those contexts, it might screw your time :/ 所以在使用这些上下文时要小心,这可能会让你的时间变得紧张:/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.