Android 仪器测试中的 Dagger 2 注入
Posted
技术标签:
【中文标题】Android 仪器测试中的 Dagger 2 注入【英文标题】:Dagger 2 injection in Android instrumentation tests 【发布时间】:2021-10-16 22:33:24 【问题描述】:我正在尝试在我的 android 仪器测试中使用 Dagger 2 进行 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>
而匕首相关代码如下:
测试组件
@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 测试类中?
【问题讨论】:
【参考方案1】:您的匕首设置中似乎缺少一些步骤,我已经包含了一个我使用的清单。
创建 CustomTestRunnerclass 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)
测试应用程序
class MyTestApplication : MyApplication()
override fun initializeComponent(): AppComponent
// Creates a new TestAppComponent that injects fakes types
return DaggerTestAppComponent.create()
如果您正在寻找有关每个步骤的更多详细信息,您可以找到该信息here。
【讨论】:
以上是关于Android 仪器测试中的 Dagger 2 注入的主要内容,如果未能解决你的问题,请参考以下文章
如何在 android 中使用 dagger 对 kotlin 文件进行 UI 测试?
单元/仪器测试 Android Gradle。仪器测试不会运行