Android Mocking Dagger2 Introduces Addiction for Espresso Test

I have an intensive addiction application (dagger2). I would like to run an espresso test without checking the test through the entire application, and enter the application.

I would like to start with my teleActivity and make fun of the entry manager. However, in any @test function, we already hit the null pointer, as we called onCreate. If I override this before we run the action (show below), the action will be null.

As far as I understand, the ability to switch our underline dependencies is the big reason we use Dagger2, otherwise it will be just a redesigned singleton. How to override, make fun of or switch the injection into the dagger testing module, so I can create this simple espresso test.

Note. I also wrote all this in the MVP design pattern, if that matters.

TeleActivity

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

Espresso

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

Dagger injector

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

TelePresenterComponent

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

TelePresenterModule

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

LoginStateManagerModule

 @Module public class LoginStateManagerModule { @Provides @Singleton public LoginStateManager getLoginStateManager(){ return new LoginStateManager(); } } 
+5
source share
3 answers

Firstly, your decision to use dependency injection (Dagger2) is very good and will really simplify your tests.

You must redefine the dependency injection configuration (module) and enter the layout. Here is a simple example of how this can be done.

First you need a layout:

 LoginStateManager lsmMock = mock(LoginStateManager.class); 

Now redefine the DI configuration to use this layout:

 //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

+5
source

It looks like an architecture issue, not a minor issue.

First, I would not create a static class to call the dagger2 component. My approach would be more Android-oriented, I mean using the singleton application with all its bells and whistles.

In any case ... The best way to start testing without completing the entire workflow is to separate the project from two different projects:

1-UI application, your actions and fragments of Android, etc.

2-Logic module using enterprise architecture says MVP / MVC / MVVM (this should be another project inside your android studio)

Where should you use a dagger? inside your user interface to insert a logic module into your interface.

How can you test another part of the application (logic module)? since you separated your logic into different parts, it would be much easier to write tests for them, even if you no longer need Esperesso. simple unit testing with JUnit and Mockito can help you without having to complete the entire workflow.

note that there should be no logic in your user interface.

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

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

0
source

no value set in

LoginStateManager

therefore, when you create the component, you get both the TelePresenter Dependency dependency and the LoginStateManager dependency but there are no values โ€‹โ€‹set in the member variables of both. Therefore, I think you need to set the values โ€‹โ€‹of member variables before accessing them.

 getBaseLoginResponse().getAccessToken()) 

the above line of code gives you a null value because you did not set the value. Therefore, before accessing it, you need to first set the values

0
source

Source: https://habr.com/ru/post/1266096/


All Articles