Hilt 测试最佳实践 | MAD Skills
Hilt
https://dagger.dev/hilt/
如果您更喜欢通过视频了解此内容,可以在此处查看:
Hilt 的测试理念
由于 Hilt 是一个有特定处理原则的框架,所以它的测试 API 是基于一些特定目标创建的。了解 Hilt 用于测试的方法有助于您使用和理解它的 API。如需进一步了解测试理念的更多信息,请参阅: Hilt 的测试理念。
Hilt 的测试理念
https://dagger.dev/hilt/testing-philosophy
Dagger
https://dagger.dev/
手动实例化 (测试时不使用 Hilt)
class EventManager @Inject constructor(
dataModel: DataModel,
errorHandler: ErrorHandler
) {}
@RunWith(JUnit4::class)
class EventManagerTest {
@Test
fun testEventManager() {
val eventManager = EventManager(dataModel, errorHandler)
// 测试代码
}
}
@RunWith(JUnit4::class)
class EventManagerTest {
@Test
fun testEventManager() {
// 呃...changeNotifier 要怎么处理?
val dataModel = DataModel(changeNotifier)
val errorHandler = ErrorHandler(errorConfig)
val eventManager = EventManager(dataModel, errorHandler)
// 测试代码
}
}
我们也可以直接实例化这些对象,但是如果这些对象同样包含依赖,那么继续下去可能会过于深入。在进行实际测试前,我们最终可能会调用很多个构造函数。另外,这些构造函数的调用也会使测试变得脆弱。任何一个构造函数的改变都会破坏测试,即使它们在生产环境中没有破坏任何内容。本应为 "无操作" 的更改,例如在 @Inject 构造函数中改变参数顺序,或者通过 @Inject 构造函数为某个类添加依赖,都会破坏测试且难以对其进行更新。
使用 Hilt 进行测试
若要在您的测试中配置 Hilt,您需要:
为您的测试添加 @HiltAndroidTest 注解
https://dagger.dev/api/latest/dagger/hilt/android/testing/HiltAndroidTest.html
添加测试规则 HiltAndroidRule
https://dagger.dev/api/latest/dagger/hilt/android/testing/HiltAndroidRule.html
为 Application 类使用 HiltTestApplication
https://dagger.dev/api/latest/dagger/hilt/android/testing/HiltTestApplication.html
对于第三步来说,如何使用 HiltTestApplication 取决于您测试的类型:
对于 Robolectric 测试,请查阅:
https://dagger.dev/hilt/robolectric-testing
对于插桩测试,请查阅:
https://dagger.dev/hilt/instrumentation-testing
@HiltAndroidTest
@RunWith(AndroidJUnit4::class)
class EventManagerTest {
@get:Rule
val rule = HiltAndroidRule(this)
@Inject
lateinit var eventManager: EventManager
@Before
fun setup() {
rule.inject(this)
}
@Test
fun testEventManager() {
// 使用注入的 eventManager 进行测试
}
}
SingletonComponent,ActivityComponent,FragmentComponent
https://dagger.dev/hilt/components
TestInstallIn
当您在测试中遇到需要替换依赖的情况,比如真实对象会做诸如调用服务器这样的昂贵操作时,您可以使用 TestInstallIn 来进行替换。
TestInstallIn
https://dagger.dev/hilt/testing#testinstallin
@Module
@TestInstallIn(
components = [SingletonComponent::class],
replaces = [BackendModule::class]
)
object FakeBackendModule {
@Singleton
@Provides
fun provideBackend(): BackendClient {
return FakeBackend.inMemoryBackendBuilder(
/* ...虚拟后台数据... */
).build()
}
}
UninstallModules
@HiltAndroidTest
@RunWith(AndroidJUnit4::class)
@UninstallModules(BackendModule::class)
class DataFetcherTest {
@BindValue
val fakeBackend = FakeBackend.inMemoryBackendBuilder(...).build()
...
}
UninstallModules
https://dagger.dev/hilt/testing#uninstall-modules@BindValue
https://dagger.dev/hilt/testing#bind-value
TestInstallIn vs UninstallModules
TestInstallIn
应用于全局
便于配置
利于提升构建速度
UninstallModules
只针对单个测试
非常灵活
不利于构建速度
TestInstallIn/UninstallModules 影响构建速度的原因
测试依赖
△ 尽可能将测试组织到依赖库 Gradle 模块中
组织 Hilt 模块
更多资源
有关使用 Hilt 进行测试的更多信息,请查阅:
完整文档
https://dagger.dev/hilt/testing 内含更多示例的测试指南文档
https://developer.android.google.cn/training/dependency-injection/hilt-testing
欢迎您通过下方二维码向我们提交反馈,或分享您喜欢的内容、发现的问题。您的反馈对我们非常重要,感谢您的支持!
推荐阅读