Контекст
У меня есть Android приложение, написанное на Kotlin с использованием Dagger (v. 2.27). В своих тестах я создаю реальные экземпляры некоторых зависимостей и некоторых из этих зависимостей @Inject
a CoroutineDispatcher
.
Цель
Разрешить в моих тестах опционально указывать тест CoroutineDispatcher
для использования тестовым компонентом Кинжала. Некоторые тесты не нуждаются в такой дополнительной конфигурации, и они должны автоматически получать предопределенный диспетчер тестов.
Как
У меня есть модуль, который предоставляет @BindsOptionalOf
для @TestIODispatcher CoroutineDispatcher
.
- Когда для теста требуется пользовательский диспетчер, он может вручную связать его с фабрикой TestComponent.
- Когда тесту не нужен какой-либо специальный диспетчер, он должен автоматически получить TestCoroutineDispatcher () .
@Module
abstract class RepositoryTestModule {
@Retention(AnnotationRetention.RUNTIME)
annotation class TestIODispatcher
@BindsOptionalOf
@TestIODispatcher
abstract fun testIODispatcher(): CoroutineDispatcher
@Module
companion object {
@Provides
@IODispatcher
fun coroutineDispatcher(
@TestIODispatcher testIODispatcher: Optional<CoroutineDispatcher>): CoroutineDispatcher {
return testIODispatcher.orElse(TestCoroutineDispatcher())
}
}
}
В моем тесте я создаю TestComponent с фабрикой, которая принимает @BindsInstance @TestIODispatcher
.
@Singleton
@Component(modules = [RepositoryTestModule::class])
interface TestComponent {
fun inject(...)
@Component.Factory
interface Factory {
fun create(
@BindsInstance @TestIODispatcher ioDispatcher: CoroutineDispatcher) : TestComponent
}
}
Я передаю свой собственный диспетчер только для тестирования в качестве аргумента фабрика во время определения компонента.
DaggerAppNameViewModelTest_TestComponent
.factory()
.create(Dispatchers.IO)
Проблема
Компиляция моего теста завершается с ошибкой [Dagger / DependencyCycle].
public static abstract interface TestComponent {
^
java.util.Optional<kotlinx.coroutines.CoroutineDispatcher> is injected at
com.example.<appname>.repository.RepositoryTestModule.Companion.coroutineDispatcher(testIODispatcher)
kotlinx.coroutines.CoroutineDispatcher is injected at
...
Я не совсем вижу цикл зависимости, поскольку мой @IODispatcher CoroutineDispatcher
зависит от @TestIODispatcher CoroutineDispatcher
, который явно связан с тестом.
Моя теория состоит в том, что Kotlin каким-то образом удаляет аннотации, а затем он просто сравнивает привязки по типам. В этом случае действительно был бы цикл.
Я пропустил очевидный цикл или мне нужно что-то сделать с аннотациями?