[英]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
類,而不是在ExampleInstrumentedTest
中ExampleInstrumentedTest
了我如何編輯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組件,而無需在測試中再次進行。 讓androidInjector
被AndroidTestAppComponent
而不是AndroidInjector
在AndroidTestApplicaiton
,做一個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.