Я пишу UnitTests для ViewModel / StateMachine (используя шаблон MVI). ViewModel имеет встроенный API-компонент (встроенный с Retrofit)
class UserViewModel(
private val API: API
)
object UserModule {
fun get(): Module {
return module {
viewModel { UserViewModel(api = get()) }
}
}
}
object NetworkModule {
fun get(): Module {
return module {
... // various retrofit Beans
single{ Api(retrofit = get()) }
}
}
}
Это работает в моем приложении, но когда UnitTesting я должен был заглушить ответы от API
, в одном тесте заглушить его с ошибкой, вдругая заглушка с ложным ответом, так что наличие некоторого MockNetworkModule, MockFailingNetworkModule
с тем же интерфейсом кажется излишним, и это не так быстро, как подготовка фиктивных данных в блоке тестового кода.
Вот как япопытайтесь заглушить вызовы, но он все еще использует старую реализацию и выполняет сетевые вызовы
class UserTest : KoinTest {
@get:Rule
val schedulers = RxImmediateSchedulerRule()
private val viewModel: UserViewModel by inject()
@Before
fun before() {
startKoin {
modules(
listOf(
UserModule.get(),
NetworkModule.get()
)
)
}
}
@After
fun after() {
stopKoin()
}
}
Мои тесты написаны так (аналогично тому, что я прочитал из документации Koin):
@Test
fun `user test passing`() {
val mockUserData = UserData("name", "surname")
declareMock<Api> {
given(this.getUserData()).willReturn { Single.just(mockUserData) }
}
viewModel.refresh() // calls api.getUserData() inside
... expecting mockUserData but getting real api call
}
@Test
fun `user test failing`() {
declareMock<Api> {
given(this.getUserData()).willReturn { Single.error(Exception("mock")) }
}
viewModel.refresh() // calls api.getUserData() inside
... expecting exception but getting real api call
}
Я также пытался declareMock<UserViewModel>{ given(this.api.getUserData()} ...
, но имел NullPointerException
на this.api
.
TL; DR Как правильно заглушить уже внедренный компонент внутри viewModel для UnitTestingна лету