簡體   English   中英

Dagger2注射單元測試為空

[英]Dagger2 Injection Unit Tests is null

嗨,我已經使用匕首在我的應用程序中對網絡模塊,ApplicationModule,DatabaseModule,Presenter和交互器進行依賴項注入。 我想在單元測試期間使用這些相同的類和模塊。

作為單元測試參考,我使用以下代碼創建了AndroidTestAppComponent:

@Singleton
@Component(modules = {
        AndroidSupportInjectionModule.class,
        AndroidTestAppModule.class,
        NetworkModule.class
})
public interface AndroidTestAppComponent extends AndroidInjector<AndroidTestApplication> {
    @Component.Builder
    abstract class AndroidTestAppComponentBuilder extends Builder<AndroidTestApplication> {
    }
}

考慮AndroidTestAppModule.java below所有模塊超出此問題的范圍,請考慮AndroidTestAppModule.java below

public class AndroidTestAppModule {
    @Provides
    @Singleton
    Context provideContext(AndroidTestApplication application) {
        return application.getApplicationContext();
    }

    @Singleton
    @Provides
    KeyguardManager provideKeyguardManager(Context context) {
        return (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
    }

    @Singleton
    @Provides
    FingerprintManagerCompat providerFingerPrintManager(Context context) {
        return FingerprintManagerCompat.from(context);
    }
}

我能夠生成DaggerAndroidTestAppComponent 我的應用程序類如下:

public class AndroidTestApplication extends DaggerApplication implements HasActivityInjector {
    @Inject
    DispatchingAndroidInjector<Activity> dispatchingActivityInjector;

    AndroidInjector<AndroidTestApplication> androidInjector;

    @Override
    public void onCreate() {
        super.onCreate();
        androidInjector.inject(this);
    }

    @Override
    protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
        androidInjector = DaggerAndroidTestAppComponent.builder().create(this);
        return androidInjector;
    }

    @Override
    public DispatchingAndroidInjector<Activity> activityInjector() {
        return dispatchingActivityInjector;
    }
}

其他一些AppPref.java

@Singleton
public class AppPref {

    private SharedPreferences preferences;

    @Inject
    AppPref(Context context) {
        preferences = context.getSharedPreferences("somefile", Activity.MODE_PRIVATE);
    }
}

正如從文檔中讀取的那樣: AndroidInjection#inject(T t) t在這里需要核心的android模塊,所以當我在Activity AndroidInjection.inject(activity_reference_usually__this__)調用它時,它可以正常工作(正常情況下,實際構建並且沒有測試應用程序)

在不更改太多代碼的情況下,我將如何在AndroidInstrumentationTest中使用這些類,因為我只會在測試包內的Test**DaggerModules更改測試實現。

儀器的示例代碼如下:

@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {


    AndroidTestApplication application;

    @Inject
    AppPref appPref;


    @Before
    public void setUp() throws IllegalAccessException, InstantiationException, ClassNotFoundException {
        Context appContext = InstrumentationRegistry.getTargetContext();
        application = (AndroidTestApplication) Instrumentation.newApplication(AndroidTestApplication.class, appContext);
        DaggerAndroidTestAppComponent.builder().create(application).inject(application);
    }

    @Test
    public void useAppContext() {
        // Context of the app under test.
        Context appContext = InstrumentationRegistry.getTargetContext();

        assertEquals("com.a.b", appContext.getPackageName());
    }

    @Test
    public void testPreNotNUll() {
        Assert.assertNotNull(appPref);
    }

}

理想情況下,apppref始終為null,因為在setUp方法中我已經注入了ExampleInstrumentedTest類,而不是在ExampleInstrumentedTestExampleInstrumentedTest了我如何編輯dagger2代碼,以便@Inject可以正常工作並獲得有效的appPref對象。 謝謝。

實際上,您實際上沒有在Test類中注入任何東西。 DaggerAndroidTestAppComponent.builder().create(application).inject(application); 您正在注入AndroidTestApplication而不是Test。

嘗試添加

void inject(ExampleInstrumentedTest test);

進入您的組件界面。

@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
    androidInjector = DaggerAndroidTestAppComponent.builder().create(this);
    return androidInjector;
}

在這里,您將創建Dagger組件,而無需在測試中再次進行。 androidInjectorAndroidTestAppComponent而不是AndroidInjectorAndroidTestApplicaiton ,做一個getter方法在該組件AndroidTestApplication ,然后在測試setUp方法使用application.getComponent().inject(this); 這樣,您就可以將依賴項注入所需的類(即Test)中。

我不得不修改@Component接口,以跳過從AndroidInjector.Builder擴展擴展AndroidInjector.Builder並提供自己的方法。

@Singleton
@Component(modules = {
        AndroidSupportInjectionModule.class,
        AndroidTestAppModule.class,
        NetworkModule.class
})
public interface AndroidTestAppComponent extends AndroidInjector<AndroidTestApplication> {
    void inject(ExampleInstrumentedTest test);

    @Component.Builder
    abstract class AndroidTestAppComponentBuilder {
        @BindsInstance
        public abstract AndroidTestAppComponentBuilder application(AndroidTestApplication application);

        public abstract AndroidTestAppComponent build();
    }
}

這樣,我必須手動傳遞應用程序並構建組件,然后根據tuby的建議,我必須向@Component接口添加新方法void inject(ExampleInstrumentedTest test)

我的測試類現在看起來像這樣,我可以運行測試並獲得覆蓋率[jacoco工具]:

@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {


    @Inject
    AppPref appPref;


    @Before
    public void setUp() throws IllegalAccessException, InstantiationException, ClassNotFoundException {
        Context appContext = InstrumentationRegistry.getTargetContext();
        AndroidTestApplication application = (AndroidTestApplication) Instrumentation
                .newApplication(AndroidTestApplication.class, appContext);
        DaggerAndroidTestAppComponent.builder().application(application)
                .build()
                .inject(this);

    }

    @Test
    public void test1AppPrefNotNUll() {
        Assert.assertNotNull(appPref);
    }


    private final String KEY = "key";
    private final String valid = "test_app";
    private final String invalid = "non_app";


    @Test
    public void test2AppPrefWrite() {
        appPref.writePreference(KEY, valid);
        Assert.assertNotNull(appPref.readPreference(KEY));
    }

    @Test
    public void test3AppPrefRead() {
        Assert.assertEquals(valid, appPref.readPreference(KEY));
    }

    @Test
    public void test4AppPrefInvalid() {
        Assert.assertNotNull(invalid, appPref.readPreference(KEY));
    }

    @Test
    public void test5AppPrefClear() {
        appPref.clearPreferences();
        Assert.assertEquals(0, appPref.size());
    }

}

暫無
暫無

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

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