【问题标题】:Test instrumentation process crashed when injecting mocked object注入模拟对象时测试检测过程崩溃
【发布时间】:2017-12-07 12:05:50
【问题描述】:

我正在尝试运行 UI 测试。当我不模拟任何注入的依赖项时,一切都运行良好。当我切换模块的 @Provides 返回到模拟对象时,我收到以下消息:

开始运行测试

测试仪器过程崩溃。

检查 com.nerfy.features.core.CoreTest#a_shouldDisplayLocationPermissionRequestDialogAtStartup.txt 了解详情。

测试运行完成。

我在任何地方都找不到这个 txt 文件,只有一些根本没有信息的测试 xml。

编辑:该文件仅包含:INSTRUMENTATION_RESULT: shortMsg=Process crashed。 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 是在测试活动规则的 beforeActivityLaunched 之前调用的,尽管在某些教程中他们说它应该在应用程序创建之前调用。

我遵循了类似的教程 http://blog.sqisland.com/2015/04/dagger-2-espresso-2-mockito.html

Android Mocking a Dagger2 injected dependency for a Espresso test

How do you override a module/dependency in a unit test with Dagger 2.0?

和类似的;也是官方 dagger2 文档。

我已经尝试子类化应用程序,创建新模型和子类化组件仅用于测试;也不会在 setUp() 结束之前初始化 activityRule,在此处注入组件之后,而不是覆盖 beforeActivityLaunched()。

还尝试了一些琐碎的修复,例如重建项目、重新启动 android studio、更新依赖项。

模拟一些其他模块也能带来相同的结果,而模拟其他模块效果很好。

有什么想法吗?

【问题讨论】:

  • 查看stackoverflow.com/questions/46435789/…如何获取错误信息中的TXT日志文件引用
  • 感谢您的链接。该文件仅包含: INSTRUMENTATION_RESULT: shortMsg=进程崩溃。 INSTRUMENTATION_CODE:0 一点用都没有。

标签: android mockito android-espresso dagger-2 functional-testing


【解决方案1】:

我已经测试了其他模块。发现模拟的 Refresher 模块由于具有 Observable 字段而会使测试过程崩溃。测试的活动尝试订阅它,但它是空的。

SharedData 更难弄清楚 - 它处理共享首选项,所以基本上只是字符串和布尔值。我必须检查所有用法。尝试将字符串值作为 url(未模拟,因此再次为 null)到 Picasso 以获取图像时发生崩溃。

故事的寓意 - 一条正确的崩溃消息值得两天盲目调试。

【讨论】:

    【解决方案2】:

    我认为问题出在System.out.print 方法上。尝试删除所有这些并运行代码。

    使用Log.eLog.i 代替获取输出,稍后拉取日志。

    【讨论】:

      【解决方案3】:

      对我来说,我无法在模拟器上运行我的 UI 仪器测试,只能在物理设备上运行。切换到使用 64 位 x86 ABI 解决了这个问题。 https://github.com/android/android-test/issues/352

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-23
        • 1970-01-01
        • 2018-11-04
        • 2015-04-25
        • 1970-01-01
        • 2014-04-16
        • 2019-11-27
        • 1970-01-01
        相关资源
        最近更新 更多