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 can I use CClistview in COCOS2d Android?(如何在 COCOS2d Android 中使用 CClistview?)
cocos2d-android: how to display score(cocos2d-android:如何显示分数)
Sqlite database not copied from asset folder Android(Sqlite 数据库未从资产文件夹 Android 复制)
SQLite Database Copy Appears Corrupted When Generated by Device and not Emulator(SQLite 数据库副本在由设备而不是模拟器生成时出现损坏)
Android file copy(安卓文件拷贝)
Android how to detect Copy event of Edittext in android(Android如何在android中检测Edittext的Copy事件)