getTargetContext() 和 getContext(在 InstrumentationRegistry 上)有什么区别?
What's the difference between getTargetContext() and getContext (on InstrumentationRegistry)?
我正在使用新的 Android 测试支持库 (com.android.support.test:runner:0.2
) 进行 运行 仪器测试
(a.k.a 设备或模拟器测试)。
我用 @RunWith(AndroidJUnit4.class)
注释我的测试 class 并使用 Android Studio 来 运行 它们。
对于我的测试用例,我需要一个 Context
实例。我可以用 InstrumentationRegistry
得到它,但它有两个上下文相关的方法,不清楚有什么区别。
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.getInstrumentation()
, returns the
Instrumentation currently running.
InstrumentationRegistry.getContext()
, returns the Context of this
Instrumentation’s package.
InstrumentationRegistry.getTargetContext()
,
returns the application Context of the target application.
InstrumentationRegistry.getArguments()
, returns a copy of arguments
Bundle that was passed to this Instrumentation. This is useful when
you want to access the command line arguments passed to
Instrumentation for your test.
编辑:
So when to use getContext() vs getTargetContext()?
文档没有很好地解释差异,所以这是我的 POV:
您知道,当您在 Android 上进行仪器测试时,您有两个应用程序:
- 测试应用程序,执行您的测试逻辑并测试您的 "real" 应用程序
- "real" 应用(您的用户将会看到)
因此,当您编写测试并且想要加载真实应用程序的资源时,请使用getTargetContext()
。
如果您想使用测试应用程序的资源(例如,您的一项测试的测试输入),请调用getContext()
。
您可能需要 InstrumentationRegistry.getContext()
才能访问测试用例的原始资源。
例如,要在测试用例中访问 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);
我花了好几个小时才弄明白。
InstrumentedTest 用例有一个上下文成员,它在设置中设置如下:
context = InstrumentationRegistry.getTargetContext();
这用于打开文件,尤其是类似的东西:
String filenameOriginal = context.getCacheDir() + "/initial.csv";
现在我决定我需要使用一些 仅 在插桩测试中可用的资源,我不想将此资源与发布版本一起分发。
因此我重新创建了测试下的资源目录:
app\src\androidTest
└───res
└───raw
v1.csv
但是为了能够在代码中使用它,我必须这样调用:
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)
这 总是 失败,因为 R.raw.v1 巧合地对应于主应用程序中我的 R
资源文件中实际存在的内容。通过在插桩测试中使用资源,生成了两个 R
文件。为了解决这个问题,我必须包含测试 R 文件:
import com.my_thing.app.my_app.test.R;
resourceToUri
调用仍然会失败。
问题是,我一定没有使用 InstrumentationRegistry.getTargetContext()
而是 InstrumentationRegistry.getInstrumentation().getContext()
来获取 R.raw.v1
的资源,所以我盲目地替换了整个测试的上下文设置class 到
context = InstrumentationRegistry.getInstrumentation().getContext();
它在特定测试中运行良好,但测试用例中的其他测试开始失败,因为我在上面使用的 filenameOriginal
权限被拒绝。
原来,通过将上下文替换为检测上下文,我获得了我的应用程序无法访问的路径,我得到了 FileNotFoundException
和 permission denied
而没有 GrantTestRule
或其他事情会成功的。
所以在使用这些上下文时要小心,它可能会浪费你的时间:/
我正在使用新的 Android 测试支持库 (com.android.support.test:runner:0.2
) 进行 运行 仪器测试
(a.k.a 设备或模拟器测试)。
我用 @RunWith(AndroidJUnit4.class)
注释我的测试 class 并使用 Android Studio 来 运行 它们。
对于我的测试用例,我需要一个 Context
实例。我可以用 InstrumentationRegistry
得到它,但它有两个上下文相关的方法,不清楚有什么区别。
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.getInstrumentation()
, returns the Instrumentation currently running.InstrumentationRegistry.getContext()
, returns the Context of this Instrumentation’s package.InstrumentationRegistry.getTargetContext()
, returns the application Context of the target application.InstrumentationRegistry.getArguments()
, returns a copy of arguments Bundle that was passed to this Instrumentation. This is useful when you want to access the command line arguments passed to Instrumentation for your test.
编辑:
So when to use getContext() vs getTargetContext()?
文档没有很好地解释差异,所以这是我的 POV:
您知道,当您在 Android 上进行仪器测试时,您有两个应用程序:
- 测试应用程序,执行您的测试逻辑并测试您的 "real" 应用程序
- "real" 应用(您的用户将会看到)
因此,当您编写测试并且想要加载真实应用程序的资源时,请使用getTargetContext()
。
如果您想使用测试应用程序的资源(例如,您的一项测试的测试输入),请调用getContext()
。
您可能需要 InstrumentationRegistry.getContext()
才能访问测试用例的原始资源。
例如,要在测试用例中访问 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);
我花了好几个小时才弄明白。
InstrumentedTest 用例有一个上下文成员,它在设置中设置如下:
context = InstrumentationRegistry.getTargetContext();
这用于打开文件,尤其是类似的东西:
String filenameOriginal = context.getCacheDir() + "/initial.csv";
现在我决定我需要使用一些 仅 在插桩测试中可用的资源,我不想将此资源与发布版本一起分发。 因此我重新创建了测试下的资源目录:
app\src\androidTest
└───res
└───raw
v1.csv
但是为了能够在代码中使用它,我必须这样调用:
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)
这 总是 失败,因为 R.raw.v1 巧合地对应于主应用程序中我的 R
资源文件中实际存在的内容。通过在插桩测试中使用资源,生成了两个 R
文件。为了解决这个问题,我必须包含测试 R 文件:
import com.my_thing.app.my_app.test.R;
resourceToUri
调用仍然会失败。
问题是,我一定没有使用 InstrumentationRegistry.getTargetContext()
而是 InstrumentationRegistry.getInstrumentation().getContext()
来获取 R.raw.v1
的资源,所以我盲目地替换了整个测试的上下文设置class 到
context = InstrumentationRegistry.getInstrumentation().getContext();
它在特定测试中运行良好,但测试用例中的其他测试开始失败,因为我在上面使用的 filenameOriginal
权限被拒绝。
原来,通过将上下文替换为检测上下文,我获得了我的应用程序无法访问的路径,我得到了 FileNotFoundException
和 permission denied
而没有 GrantTestRule
或其他事情会成功的。
所以在使用这些上下文时要小心,它可能会浪费你的时间:/