注入模拟对象时测试仪器进程崩溃
Test instrumentation process crashed when injecting mocked object
我正在尝试 运行 UI 测试。当我不模拟任何注入的依赖项时,一切 运行 都很好。当我将模块的 @Provides return 切换为模拟对象时,我收到以下消息:
Started running tests
Test instrumentation process crashed.
Check
com.nerfy.features.core.CoreTest#a_shouldDisplayLocationPermissionRequestDialogAtStartup.txt
for details.
Tests ran to completion.
我在任何地方都找不到这个 txt 文件,只有一些根本没有信息的测试 xml。
编辑: 该文件仅包含:INSTRUMENTATION_RESULT:shortMsg=进程崩溃。 INSTRUMENTATION_CODE: 0.
应用在其他方面运行良好。
申请代码:
public class Nerfy extends Application {
private AppComponent appComponent;
public static Nerfy get(Context context) {
return (Nerfy) context.getApplicationContext();
}
@Override
public void onCreate() {
super.onCreate();
System.out.println("on create");
if (appComponent == null) {
appComponent = buildProdAppComponent();
appComponent.inject(this);
}
}
public AppComponent buildProdAppComponent() {
return DaggerAppComponent.builder()
.appModule(new AppModule(this))
.navigationModule(new NavigationModule())
.refreshModule(new RefreshModule())
.repoModule(new RepoModule())
.sharedDataModule(new SharedDataModule())
.threadsModule(new ThreadsModule())
.build();
}
//@VisibleForTesting
public void setAppComponent(AppComponent appComponent) {
System.out.println("on set");
this.appComponent = appComponent;
this.appComponent.inject(this);
}
public AppComponent getAppComponent() {
return appComponent;
}
}
这是一些测试代码:
@RunWith(AndroidJUnit4.class)
@LargeTest
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class CoreTest {
private UiDevice device;
public SharedData sharedData;
private AppComponent espressoAppComponent;
@Rule
public ActivityTestRule<Core> mActivityRule =
new ActivityTestRule<Core>(Core.class) {
@Override
protected void beforeActivityLaunched() {
System.out.println("beforeActivityLaunched");
sharedData = mock(SharedData.class);
System.out.println("shared data " + sharedData);
espressoAppComponent = DaggerAppComponent.builder()
.appModule(new AppModule((Application) getTargetContext().getApplicationContext()))
.navigationModule(new NavigationModule())
.refreshModule(new RefreshModule())
.repoModule(new RepoModule())
.sharedDataModule(new SharedDataModule(){
@Override
public SharedData providesSharedData(Application application) {
return sharedData;
}
})
.threadsModule(new ThreadsModule())
.build();
((Nerfy) getTargetContext().getApplicationContext()).setAppComponent(espressoAppComponent);
super.beforeActivityLaunched();
}
};
@Before
public void setUp() {
}
@Test
@SdkSuppress(minSdkVersion = 23)
public void a_shouldDisplayLocationPermissionRequestDialogAtStartup() throws Exception {
assertViewWithTextIsVisible(device, TEXT_ALLOW);
assertViewWithTextIsVisible(device, TEXT_DENY);
denyCurrentPermission(device);
}
没有打印出来。
但是如果我将模拟的共享数据切换为真实的共享数据
@Override
public SharedData providesSharedData(Application application) {
return super.providesSharedData(application);
一切 运行 很好,测试正常失败,因为没有模拟共享数据。
然后我还注意到应用程序的 onCreate 在测试 activity 规则的 beforeActivityLaunched 之前被调用,尽管在一些教程中他们说它应该在创建应用程序之前被调用。
我已经学习了像这样的教程
http://blog.sqisland.com/2015/04/dagger-2-espresso-2-mockito.html
How do you override a module/dependency in a unit test with Dagger 2.0?
和类似的;也是官方的 dagger2 文档。
我试过子类化应用程序,创建新模型和子类化组件仅用于测试;在 setUp() 结束之前也不会启动 activityRule,在此处注入组件而不是覆盖 beforeActivityLaunched() 之后。
还尝试了一些琐碎的修复,例如重建项目、重新启动 android studio、更新依赖项。
模拟其他一些模块也会产生相同的结果,而模拟其他模块则工作正常。
有什么想法吗?
我已经测试了其他模块。发现模拟的 Refresher 模块会因为具有 Observable 字段而导致测试过程崩溃。测试的 activity 尝试订阅它,但它是空的。
SharedData 更难理解 - 它处理共享首选项,所以基本上只是字符串和布尔值。我不得不检查所有的用法。尝试将字符串值作为 url(不是模拟,所以再次为 null)到 Picasso 以获取图像时发生崩溃。
故事的寓意 - 一条正确的崩溃消息值得两天的盲目调试。
我认为问题是 System.out.print
方法。尝试删除所有这些和 运行 代码。
使用 Log.e
或 Log.i
,而不是获取输出,稍后拉取日志。
对我来说,我无法 运行 我的 UI 模拟器测试,只能在物理设备上进行。切换到使用 64 位 x86 ABI 解决了这个问题。
https://github.com/android/android-test/issues/352
我正在尝试 运行 UI 测试。当我不模拟任何注入的依赖项时,一切 运行 都很好。当我将模块的 @Provides return 切换为模拟对象时,我收到以下消息:
Started running tests
Test instrumentation process crashed.
Check com.nerfy.features.core.CoreTest#a_shouldDisplayLocationPermissionRequestDialogAtStartup.txt for details.
Tests ran to completion.
我在任何地方都找不到这个 txt 文件,只有一些根本没有信息的测试 xml。
编辑: 该文件仅包含:INSTRUMENTATION_RESULT:shortMsg=进程崩溃。 INSTRUMENTATION_CODE: 0.
应用在其他方面运行良好。
申请代码:
public class Nerfy extends Application {
private AppComponent appComponent;
public static Nerfy get(Context context) {
return (Nerfy) context.getApplicationContext();
}
@Override
public void onCreate() {
super.onCreate();
System.out.println("on create");
if (appComponent == null) {
appComponent = buildProdAppComponent();
appComponent.inject(this);
}
}
public AppComponent buildProdAppComponent() {
return DaggerAppComponent.builder()
.appModule(new AppModule(this))
.navigationModule(new NavigationModule())
.refreshModule(new RefreshModule())
.repoModule(new RepoModule())
.sharedDataModule(new SharedDataModule())
.threadsModule(new ThreadsModule())
.build();
}
//@VisibleForTesting
public void setAppComponent(AppComponent appComponent) {
System.out.println("on set");
this.appComponent = appComponent;
this.appComponent.inject(this);
}
public AppComponent getAppComponent() {
return appComponent;
}
}
这是一些测试代码:
@RunWith(AndroidJUnit4.class)
@LargeTest
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class CoreTest {
private UiDevice device;
public SharedData sharedData;
private AppComponent espressoAppComponent;
@Rule
public ActivityTestRule<Core> mActivityRule =
new ActivityTestRule<Core>(Core.class) {
@Override
protected void beforeActivityLaunched() {
System.out.println("beforeActivityLaunched");
sharedData = mock(SharedData.class);
System.out.println("shared data " + sharedData);
espressoAppComponent = DaggerAppComponent.builder()
.appModule(new AppModule((Application) getTargetContext().getApplicationContext()))
.navigationModule(new NavigationModule())
.refreshModule(new RefreshModule())
.repoModule(new RepoModule())
.sharedDataModule(new SharedDataModule(){
@Override
public SharedData providesSharedData(Application application) {
return sharedData;
}
})
.threadsModule(new ThreadsModule())
.build();
((Nerfy) getTargetContext().getApplicationContext()).setAppComponent(espressoAppComponent);
super.beforeActivityLaunched();
}
};
@Before
public void setUp() {
}
@Test
@SdkSuppress(minSdkVersion = 23)
public void a_shouldDisplayLocationPermissionRequestDialogAtStartup() throws Exception {
assertViewWithTextIsVisible(device, TEXT_ALLOW);
assertViewWithTextIsVisible(device, TEXT_DENY);
denyCurrentPermission(device);
}
没有打印出来。
但是如果我将模拟的共享数据切换为真实的共享数据
@Override
public SharedData providesSharedData(Application application) {
return super.providesSharedData(application);
一切 运行 很好,测试正常失败,因为没有模拟共享数据。 然后我还注意到应用程序的 onCreate 在测试 activity 规则的 beforeActivityLaunched 之前被调用,尽管在一些教程中他们说它应该在创建应用程序之前被调用。
我已经学习了像这样的教程 http://blog.sqisland.com/2015/04/dagger-2-espresso-2-mockito.html
How do you override a module/dependency in a unit test with Dagger 2.0?
和类似的;也是官方的 dagger2 文档。
我试过子类化应用程序,创建新模型和子类化组件仅用于测试;在 setUp() 结束之前也不会启动 activityRule,在此处注入组件而不是覆盖 beforeActivityLaunched() 之后。
还尝试了一些琐碎的修复,例如重建项目、重新启动 android studio、更新依赖项。
模拟其他一些模块也会产生相同的结果,而模拟其他模块则工作正常。
有什么想法吗?
我已经测试了其他模块。发现模拟的 Refresher 模块会因为具有 Observable 字段而导致测试过程崩溃。测试的 activity 尝试订阅它,但它是空的。
SharedData 更难理解 - 它处理共享首选项,所以基本上只是字符串和布尔值。我不得不检查所有的用法。尝试将字符串值作为 url(不是模拟,所以再次为 null)到 Picasso 以获取图像时发生崩溃。
故事的寓意 - 一条正确的崩溃消息值得两天的盲目调试。
我认为问题是 System.out.print
方法。尝试删除所有这些和 运行 代码。
使用 Log.e
或 Log.i
,而不是获取输出,稍后拉取日志。
对我来说,我无法 运行 我的 UI 模拟器测试,只能在物理设备上进行。切换到使用 64 位 x86 ABI 解决了这个问题。
https://github.com/android/android-test/issues/352