android - 如何为每个单元测试获取我的应用程序类的新实例?

标签 android unit-testing

我有一个 Android 应用程序,它具有继承自 ApplicationMyApplication 类。

我创建了几个使用 @RunWith(AndroidJUnit4.class) 运行的单元测试。如果我分别运行每个测试,它们都会通过。如果我一起运行它们 - 第一个通过,然后(一些)其他人失败。

问题是似乎只创建了 MyApplication 的一个实例,然后它被保留并用于所有导致失败的测试,因为 MyApplication 中有一个状态 必须只初始化一次。

有没有办法运行单元测试(androidTest)以便为每个测试重新启动应用程序?我不在乎它是否会很慢(例如,每次都必须重新安装应用程序)我只希望测试能够独立运行。

单元测试的实际代码看起来像(按照@Zinc 的要求):

@RunWith(AndroidJUnit4.class)
public class AutoLogin_ActMainTest {
    @Rule
    public ActivityTestRule<ActMain> mActivityRule = new ActivityTestRule<ActMain>(
            ActMain.class) {


        @Override
        protected void beforeActivityLaunched() {
            super.beforeActivityLaunched();

            MyTestApp app = (MyTestApp) InstrumentationRegistry.getInstrumentation().getTargetContext().getApplicationContext();
            DependencyInjector.reset();
            app.reset();


            FakeUnitDaggerModule fudm = new FakeUnitDaggerModule();

            Session session = new SessionImpl(new TimeProviderImpl());
            fudm.setResMain(new ResMainTest(session));

            FakeAppPrefs appPrefs = new FakeAppPrefs();
            FakeLoginPrefs loginPrefs = new FakeLoginPrefs();
            CurrentUserHolder currentUserHolder = new CurrentUserHolder();

            FakeComponent inj = DaggerFakeComponent.builder().
                    fakeMyAppDaggerModule(new FakeMyAppDaggerModule(app, appPrefs, loginPrefs, currentUserHolder)).
                    appInfoDaggerModule(new AppInfoDaggerModule("1")).
                    fakeSessionDaggerModule(new FakeSessionDaggerModule(session)).
                    fakeExchangeDaggerModule(new FakeExchangeDaggerModule("https://test.com")).
                    fakeUnitDaggerModule(fudm).
                    build();

            DependencyInjector.init(inj);
            DependencyInjector.getInstance().inject(app);


            app.onStart();
        }
    };


    @Test
    public void testAutoLogin() {
        ElapsedTimeIdlingResource idlingResource = new ElapsedTimeIdlingResource(500);
        Espresso.registerIdlingResources(idlingResource);
        idlingResource.startWaiting();

        onView(ViewMatchers.withId(R.id.tv_logged_in_as)).check(matches(isDisplayed()));
        Espresso.unregisterIdlingResources(idlingResource);
    }
}

最佳答案

The problem is that it seems that only one instance of the MyApplication is created and then it is preserved and used for all test which causes the fails because there is a state in the MyApplication which MUST be initialized only once.

恕我直言,这是应用程序中的错误,应该修复。 Application 不适合用于许多真正的业务逻辑(尽管它可以用于初始化您的崩溃报告程序库、StrictMode 等)。其他一切都应该可以单独测试,可以直接测试,也可以通过模拟、依赖注入(inject)等方式进行测试。

话虽这么说,但有时问题不在于您控制的代码,而在于来自库或框架的代码。

Is there a way to run the unit tests (androidTest) so application is restarted for each test?

现在,是的,虽然当时没有人问这个问题。 Android Test Orchestrator (ATO) 在隔离每个测试方面做得更好,但代价是测试执行速度。

关于android - 如何为每个单元测试获取我的应用程序类的新实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39993442/

相关文章:

java - Android Fragment findViewById 在膨胀 View 后返回 Null

android - Activity onStop() 和销毁过程

java - 如何避免在 Java 测试中重复插入

c++ - 在 Gmock 的 EXPECT_CALL 之前使用 ON_CALL 时的奇怪行为

java - 如何验证构造函数中私有(private)方法调用的次数?

java - 如何更改 TTS 引擎的声音

android - IDEA报告Android Gradle Build Target错误

java - 后台多部分请求

angularjs - Angular 2 测试 - 组件状态在测试之间持续存在(即不重置)

java - 使用和不使用特定类路径文件的 JUnit 测试