Android Mocking a Dagger2 injected dependency for a Espresso test

后端 未结 3 1969
太阳男子
太阳男子 2021-02-15 11:40

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

相关标签:
3条回答
  • 2021-02-15 12:36

    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.

    First you need a mock:

    LoginStateManager lsmMock = mock(LoginStateManager.class);
    

    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;
        }
    }
    

    Now to the test:

    @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();
    }
    

    Example from: https://github.com/yuriykulikov/DIComparison/blob/master/app/src/androidTest/java/com/example/yuriy/dependencyinjectioncomparison/Dagger2Test.java

    0 讨论(0)
  • 2021-02-15 12:43

    Seems like architecture problem rather than a minor issue.

    First off I wouldn't create a static class for calling dagger2 component my approach would be more android centric, I mean using singleton application with all of its bells and whistles.

    anyway... Best way to run testing without running whole work-flow is to separate your project into two different projects:

    1- UI app, your android activities and fragments, etc...

    2-Logic Module using an enterprise architecture say MVP/MVC/MVVM (it should be a different project inside your android studio)

    Where should you use dagger? inside your UI app for sticking the logic module into your UI.

    How can you test different part of app (Logic Module)? since you separated your logic into different part writing tests for them would be much easier even though you are not gonna need Esperesso anymore. simple unit testing wiht JUnit and Mockito can help you without running the whole work-flow.

    note that you shouldn't have any kind of logic inside your UI app.

    My opinion is Clean Architecture : https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html

    I have a simple scaffold for above approach in my github you can read that too, well if you fancy : https://github.com/vahidhashemi/android_clean_architecture

    0 讨论(0)
  • 2021-02-15 12:43

    there is no value set in

    LoginStateManager

    so when you build the component you get both TelePresenter Dependency and LoginStateManager dependency but no values set in member variables of the both .So i think you need to set the values of member variables before accessing them.

    getBaseLoginResponse().getAccessToken())
    

    the above line of code is giving you null because you haven't set the value .So before accessing it you need to set the values first

    0 讨论(0)
提交回复
热议问题