Introducing the field into unit tests with dagger 2

As stated in the Dagger Documentation , for unit testing we don’t need to use a dagger at all, and for the example provided, it makes sense

class ThingDoer { private final ThingGetter getter; private final ThingPutter putter; @Inject ThingDoer(ThingGetter getter, ThingPutter putter) { this.getter = getter; this.putter = putter; } String doTheThing(int howManyTimes) { /* … */ } } 

Using this class structure, simply unit test, just mock getter and putter , pass them as constructor arguments, instruct mockito what to return when interacting with any of these objects, and then make statements on doTheThing(...) .

Where I am afraid to test when I should unit test class with a structure like this:

 class ThingDoer { @Inject ThingGetter getter; @Inject ThingPutter putter; @Inject ThingMaker maker; @Inject // other 10 objects public ThingDoer() { App.getThingComponent().inject(this); } String doTheThing(int howManyTimes) { /* … */ } } 

As you can see, I no longer use constructor injection, but instead injection. The main reason is not that there are too many parameters in the constructor.

Is there a way to inject false dependencies into ThingDoer when all its dependencies are provided via field injection?

+5
source share
1 answer

To inject fields, you can create the component and module that are used in the unit test.

Suppose you have a unit test class ThingDoerTest , you can force components to embed dependencies in ThingDoerTest instead of ThingDoer , and the module provides a mock object instead of a real object.

In my project, HomeActivity has an HomePresenter field HomePresenter . The following code is some snippets. Hope the code can give you some idea.

 @RunWith(AndroidJUnit4.class) public class HomeActivityTest implements ActivityLifecycleInjector<HomeActivity>{ @Rule public InjectorActivityTestRule<HomeActivity> activityTestRule = new InjectorActivityTestRule<>(HomeActivity.class, this); @Inject public HomePresenter mockHomePresenter; @Override public void beforeOnCreate(HomeActivity homeActivity) { Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); MyApplication myApplication = (MyApplication) instrumentation.getTargetContext().getApplicationContext(); TestHomeComponent testHomeComponent = DaggerHomeActivityTest_TestHomeComponent.builder() .appComponent(myApplication.getAppComponent()) .mockHomeModule(new MockHomeModule()) .build(); testHomeComponent.inject(HomeActivityTest.this); homeActivity.setHomeComponent(testHomeComponent); } @Test public void testOnCreate() throws Exception { verify(mockHomePresenter).start(); } @ActivityScope @Component( dependencies = { AppComponent.class }, modules = { MockHomeModule.class } ) public interface TestHomeComponent extends HomeComponent { void inject(HomeActivityTest homeActivityTest); } @Module public class MockHomeModule { @ActivityScope @Provides public HomePresenter provideHomePresenter() { return mock(HomePresenter.class); } } } 
0
source

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


All Articles