#android #unit-testing #mockito #rx-java #rx-java2
#Android #модульное тестирование #mockito #rx-java #rx-java2
Вопрос:
Я попытался получить ответ от RxJava2 в модульном тестировании, я нашел пример, как это сделать, но я не вижу ответа, вы можете мне помочь? Спасибо. Сам код работает уже давно, без проблем, и когда потребовались тесты, я столкнулся с проблемой, похожие примеры более или менее одинаковы, но везде это делается таким образом, но у меня это не работает.
Там мой код от presenter:
fun register(
email: String,
password: String,
termsEnabled: Boolean,
dayOfBirth: Int,
monthOfBirth: Int,
yearOfBirth: Int,
formattedBirthDate: String,
state: String?
) {
addDisposable(
registerUseCase.run(
RegisterUseCase.RegisterRequest(
email,
password,
termsEnabled,
formattedBirthDate,
state ?: ""
)
)
.observeOn(mainThreadScheduler)
.subscribeOn(backgroundScheduler)
.subscribe(
{
getView?.showEmptyPassword()
}, {
getView?.showEmptyPassword()
}
)
)
}
И проверить:
@Before
fun setUp() {
RxAndroidPlugins.setInitMainThreadSchedulerHandler {
Schedulers.trampoline() }
MockitoAnnotations.initMocks(this)
presenter = CreateAccountPresenter(
mainThreadScheduler,
backgroundScheduler,
registerUseCase,
getUserDataUseCase,
getStatesUseCase,
regexUtils,
router,
resourceUtils,
deviceSharedPreferences
)
presenter.setView(view)
}
@Test
fun testRegister() {
given(registerUseCase.run(RegisterUseCase.RegisterRequest(
EMAIL, PASSWORD, true,
FORMATTED_BIRTHDAY, STATE))
).willReturn(Single.just(RegisterResponse(false, "ok", "id")))
presenter.register(
EMAIL,
PASSWORD,
true,
1,
1,
1,
FORMATTED_BIRTHDAY,
STATE)
verify(view).showEmptyPassword()
}
Но проблема в том, что:
Wanted but not invoked:
view.showEmptyPassword();
-> at
com.unikrn.esports.umode.CreateAccountPresenterTest.testRegister(CreateAccountPresenterTest.kt:179)
Actually, there were zero interactions with this mock.
Комментарии:
1. Можете ли вы включить код для создания презентатора для тестов? Держу пари, что вы запускаете все в фоновой угрозе. Хотя это работает для приложения, это не будет для теста (который должен быть заблокирован)
2. Да, я пытался установить задержку в коде и в тесте, ничего не помогло
3. @Pelocho Я думаю, вы правы, но как это исправить?)
Ответ №1:
Проблема в том, что вы выполняете некоторые вычисления в фоновом потоке, и, даже будучи высмеянным, у него недостаточно времени для завершения до verify
вызова
Поскольку вы уже вводите планировщики для своих операций, укажите, что они оба есть trampoline
, поэтому все выполняется в одном потоке
@Before
fun setUp() {
presenter = CreateAccountPresenter(
Schedulers.trampoline(),
Schedulers.trampoline(),
...
)
}
В худшем случае вы можете добавить какой-нибудь блокирующий элемент (например, Semaphore
), который блокирует выполнение теста, и вы освобождаете его одним из своих view
методов (который вам нужно заглушить)
Согласно документам, Schedulers.trampoline() планирует все задачи в текущем потоке, поэтому все будет блокироваться. В случае, если вы хотите напрямую использовать некоторые планировщики, такие как Schedulers.io()
, вам нужно переопределить их аналогично тому, что вы делаете сейчас с
RxAndroidPlugins.setInitMainThreadSchedulerHandler { Schedulers.trampoline() } // Override MainThreadScheduler
Обратите внимание, что предыдущий фрагмент является всего лишь примером, и вам нужно будет его адаптировать
Комментарии:
1. Да, это работает, спасибо, но вы можете объяснить, почему? Что делают Schedulers.trampoline()?
2. И если я буду использовать just .subscribeOn(Schedulers.io ()) .observeOn(AndroidSchedulers.MainThread()) Это не сработает? И почему?
3. Поскольку вы уже использовали это в своем коде, я предположил, что вы знаете, что это такое и как это работает. Я добавлю некоторое объяснение в ответ
4. Это создал старый разработчик этого проекта, я могу использовать его, но я не знаю, почему он это сделал, вот почему я ответил
5. Я рекомендую вам ознакомиться с официальной документацией в reactivex.io . В противном случае вы столкнетесь с несколькими проблемами, которых можно легко избежать, не совершая глупых ошибок