Dagger 2在Android instrumentation测试中的注入



我试图在我的Android仪器测试中使用dagger2进行DI。它在主应用程序组件中的类/活动/片段工作得非常好,但我的测试组件似乎缺少一些我找不到的绑定。任何关于如何去做的想法将是感激的。我的代码看起来像这样:

AssetRepositoryTest

public class AssetRepositoryTest {
@Nested
@DisplayName("Given a populated database")
public class PopulatedDatabaseInstance {
@Inject
private TestDatabase database;
@Inject
private AssetRepository repository;
@BeforeEach
public void setup() {
final TestApplication application = ApplicationProvider.getApplicationContext();
application.androidInjector().inject(this);

// Setup database
}

// Tests
}
}

运行检测测试时,我得到以下异常:

java.lang.IllegalArgumentException: No injector factory bound for Class<AssetRepositoryTest.PopulatedDatabaseInstance>

,dagger相关代码如下:

TestComponent

@Singleton
@Component(modules = {
AndroidSupportInjectionModule.class,
TestPersistenceModule.class
})
public interface TestComponent extends AndroidInjector<TestApplication> {
@Component.Builder
abstract class Builder extends AndroidInjector.Builder<TestApplication> {
}
}

TestPersistenceModule

@Module(includes = TestRoomModule.class)
public abstract class TestPersistenceModule {
@Binds
abstract AssetRepository bindAssetRepository(final AssetRepositoryImpl repository);
}

TestRoomModule

@Module
public class TestRoomModule {
@Provides
@Singleton
TestDatabase provideTestDatabase(final Application application) {
return Room.inMemoryDatabaseBuilder(application, TestDatabase.class).build();
}
@Provides
@Singleton
AssetDao provideAssetDao(final TestDatabase testDatabase) {
return testDatabase.getAssetDao();
}
}

TestApplication

public class TestApplication extends DaggerApplication {
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerTestComponent.builder().create(this);
}
}

除此之外,我有一个自定义的AndroidJUnitRunner扩展类,它覆盖newApplication方法并返回测试用例的TestApplication实例。

我的AssetRepositoryImpl如下:

AssetRepositoryImpl

@Singleton
public class AssetRepositoryImpl extends AbstractRepository<Asset, AssetEntity> implements AssetRepository {
@Inject
protected WorkspaceDao workspaceDao;
@Inject
public AssetRepositoryImpl(final AssetDao dao, final AssetMapper mapper) {
super(dao, mapper);
}
}

我没有粘贴在这里的类在它们的构造函数中有@Inject注释,并且这些代码在主应用程序中与各自的主模块和组件一起正常工作。

作为最后一个想法,由JUnit实例化的AssetRepositoryTest.PopulatedDatabaseInstace因此没有被Dagger实例化,据我所知,这似乎是这里的问题。

我如何告诉Dagger如何将这些字段注入我的JUnit测试类?

似乎你在dagger设置中缺少一些步骤,我已经包含了我使用的清单。

  • 创建CustomTestRunner
class MyCustomTestRunner : AndroidJUnitRunner() {
override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application {
return super.newApplication(cl, MyTestApplication::class.java.name, context)
}
}
  • 添加到测试运行器到app/build.gradle
android {
...
defaultConfig {
...
testInstrumentationRunner "com.example.android.dagger.MyCustomTestRunner"
}
...
}
  • kapt需要对AndroidTest源代码集进行操作。
...
dependencies {
...
kaptAndroidTest "com.google.dagger:dagger-compiler:$dagger_version"
}
  • 创建测试模块
  • 创建TestAppComponent。
  • 主应用程序应该看起来像这样
open class MyApplication : Application() {
val appComponent: AppComponent by lazy {
initializeComponent()
}
open fun initializeComponent(): AppComponent {
return DaggerAppComponent.factory().create(applicationContext)
}
}
  • TestApplication
class MyTestApplication : MyApplication() {
override fun initializeComponent(): AppComponent {
// Creates a new TestAppComponent that injects fakes types
return DaggerTestAppComponent.create()
}
}

如果你想了解每个步骤的更多细节,你可以在这里找到相关信息。

最新更新