Dagger2注入装置测试为空



嗨,我已经在我的应用程序中使用dagger对网络模块、应用程序模块、数据库模块、演示者和交互程序进行了依赖注入。我想在单元测试期间使用这些相同的类和模块。

作为单元测试参考,我使用以下代码创建了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:

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模块,所以当我在活动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是alwyas null,因为在setUp方法中,我已经注入了AndroidTestApplication类,而不是在ExampleInstrumentedTest中,我如何编辑我的dagger2代码,以便@Inject正常工作,并获得有效的apppref对象。非常感谢。

您实际上并没有向Test类注入任何内容。DaggerAndroidTestAppComponent.builder().create(application).inject(application); 您正在注入AndroidTestApplication而不是您的测试。

尝试添加

void inject(ExampleInstrumentedTest test);

进入组件界面。

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

在这里,您正在创建dagger组件,无需在测试中再次进行。在AndroidTestApplicaiton中使androidInjectorAndroidTestAppComponent而不是AndroidInjector,在AndroidTestApplication中为该组件生成getter,然后在测试setUp方法中使用application.getComponent().inject(this);通过这种方式,您将依赖项注入到所需的类中,该类就是您的测试。

我不得不修改@Component接口,以跳过从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());
}
}

最新更新