Android 为 Espresso 测试模拟 Dagger2 注入依赖项

Android Mocking a Dagger2 injected dependency for a Espresso test(Android 为 Espresso 测试模拟 Dagger2 注入依赖项)
本文介绍了Android 为 Espresso 测试模拟 Dagger2 注入依赖项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个严重依赖注入的 (dagger2) 应用程序.我想运行 espresso 测试,而无需让测试浏览整个应用程序,然后登录到应用程序.

I have a heavily dependency injected (dagger2) application. I would like to run an espresso test without having the test navigate through the whole application, and log into the application.

我想开始我的远程活动,并模拟登录管理器.然而,在任何@test 函数中,我们已经在调用onCreate 时命中了空指针.如果我在启动活动(如下所示)之前覆盖它,则活动为空.

I would like to start on my teleActivity, and mock the login manager. However in any @test function, we have already hit the null pointer as we have called onCreate. If I override it before we launch the activity (show below) the activity is null.

据我了解,切换下划线依赖项的能力是我们使用 Dagger2 的一个重要原因,否则它将只是一个过度设计的单例.如何覆盖、模拟或切换到测试匕首模块的注入 - 这样我就可以创建这个简单的 espresso 测试.

To my understanding, the ability to switch our underlining dependencies is a large reason why we use Dagger2, else it would be just a very over engineered singleton. How do I override, mock, or switch the injection to a testing dagger module -- so I can create this simple espresso test.

请注意,如果有影响的话,我也在 MVP 设计模式中编写了所有这些内容.

Note I also wrote all this in the MVP design pattern if that makes a difference.

远程活动

@Inject
TelePresenter mTelePresenter;
@Inject
public LoginStateManager mLoginStateManager;

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ButterKnife.bind(this);
    DaggerInjectorTele.get().inject(this);
    mTelePresenter.setTeleDependencies(this);
    Intent intent = getIntent();

    String searchId = null;

    if (intent != null) {
        searchId = intent.getStringExtra(Constants.SEARCH_ID);
       }

    mTelePresenter.onCreateEvent(searchId,
            Helper.makeAuthorizationHeader(
            // CRASH Null pointer
            mLoginStateManager.getBaseLoginResponse().getAccessToken()));

}

浓缩咖啡

@LargeTest
@RunWith(AndroidJUnit4.class)
public class TeleTest {
    @Rule
    public ActivityTestRule<TeleActivity> mActivityTestRule = new ActivityTestRule(
            TeleActivity.class) {
        @Override
        protected void beforeActivityLaunched() {
            super.beforeActivityLaunched();
            TeleActivity teleActivity = (TeleActivity)getActivity();
             //teleActivity NULL!
            teleActivity.mLoginStateManager = mock(LoginStateManager.class);
            LoginResponse loginResponse = mock(LoginResponse.class);
            when(loginResponse.getAccessToken()).thenReturn("1234");
            // Nope here still null


when(teleActivity.mLoginStateManager.getBaseLoginResponse()).thenReturn(loginResponse);

        }
    };

匕首注射器

  public class DaggerInjectorTele {
    private static TelePresenterComponent telePresenterComponent =
            DaggerTelePresenterComponent.builder().build();

    public static TelePresenterComponent get() {
        return telePresenterComponent;
    }
}

TelePresenter组件

TelePresenterComponent

@Singleton
@Component(modules = {TelePresenterModule.class,
        LoginStateManagerModule.class})
public interface TelePresenterComponent {
    void inject(TeleActivity activity);
}

TelePresenter 模块

TelePresenterModule

@Module
public class TelePresenterModule {

    @Provides
    @Singleton
    public TelePresenter getTelePresenter() {
        return new TelePresenter();
    }
}

LoginStateManager 模块

LoginStateManagerModule

@Module
public class LoginStateManagerModule {

    @Provides
    @Singleton
    public LoginStateManager getLoginStateManager(){
        return new LoginStateManager();
    }
}

推荐答案

首先,您决定使用依赖注入 (Dagger2) 是一个非常好的决定,并且确实会让您的测试更容易编写.

First, your decision to use dependency injection (Dagger2) is a very good one and will indeed make your tests easier to write.

您必须覆盖依赖注入配置(模块)并注入一个模拟.下面是一个简单的例子来说明如何做到这一点.

You have to override dependency injection configuration (module) and inject a mock. Here is a simple example of how it can be done.

首先你需要一个模拟:

LoginStateManager lsmMock = mock(LoginStateManager.class);

现在覆盖 DI 配置以使用此模拟:

Now override the DI config to use this mock:

//Extend your TelePresenterModule, override provider method
public class TestTelePresenterModule extends TelePresenterModule{
    @Override
    public LoginStateManager getLoginStateManager() {
        //simply return the mock here
        return lsmMock;
    }
}

现在开始测试:

@Test
//this is an espresso test
public void withAMock() {
    //build a new Dagger2 component using the test override
    TelePresenterComponent componentWithOverride = DaggerTelePresenterComponent.builder()
            //mind the Test in the class name, see a class above
            .telePresenterModule(new TestTelePresenterModule())
            .build();

    //now we initialize the dependency injector with this new config
    DaggerInjectorTele.set(componentWithOverride);

    mActivityRule.launchActivity(null);

    //verify that injected mock was interacted with
    verify(lsmMock).whatever();
}

示例来自:https://github.com/yuriykulikov/DIComparison/blob/master/app/src/androidTest/java/com/example/yuriy/dependencyinjectioncomparison/Dagger2Test.java

这篇关于Android 为 Espresso 测试模拟 Dagger2 注入依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

How to target newer versions in .gitlab-ci.yml using auto devops (java 11 instead of 8 and Android 31 instead of 29)(如何在.gitlab-ci.yml中使用自动开发工具(Java 11而不是8,Android 31而不是29)瞄准较新的版本)
Android + coreLibraryDesugaring: which Java 11 APIs can I expect to work?(Android+core LibraryDesugering:我可以期待哪些Java 11API能够工作?)
How to render something in an if statement React Native(如何在If语句中呈现某些内容Reaction Native)
How can I sync two flatList scroll position in react native(如何在本机Reaction中同步两个平面列表滚动位置)
Using Firebase Firestore in offline only mode(在仅脱机模式下使用Firebase FiRestore)
Crash on Google Play Pre-Launch Report: java.lang.NoSuchMethodError(Google Play发布前崩溃报告:java.lang.NoSuchMethodError)