簡體   English   中英

使用Dagger 2進行單元測試中的現場注入

[英]Field injection in unit tests with Dagger 2

正如Dagger文檔中所建議的那樣,對於單元測試,我們根本不需要涉及Dagger,並且對於提供的示例,它是有意義的:

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) { /* … */ }
}

使用這個類結構,單元測試很簡單,只需模擬getterputter ,將它們作為構造函數參數傳遞,指示mockito在與任何這些對象交互時返回什么,然后在doTheThing(...)上進行斷言。

我在測試中苦苦掙扎的地方是我必須對類似於以下結構的類進行單元測試:

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) { /* … */ }
}

如您所見,我不再使用構造函數注入,而是使用字段注入。 主要原因是構造函數中沒有太多參數。

當使用字段注入提供所有依賴ThingDoer時,有沒有辦法在ThingDoer注入模擬依賴ThingDoer

對於現場注入,您可以創建在單元測試中使用的組件和模塊。

假設您有單元測試類ThingDoerTest ,您可以使組件向ThingDoerTest注入依賴ThingDoerTest而不是ThingDoer ,模塊提供模擬對象而不是真實對象。

在我的項目中, HomeActivity有一個現場注入HomePresenter 以下代碼是一些片段。 希望代碼可以給你一些想法。

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

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM