Тестирование сопрограмм в классе докладчика - PullRequest
8 голосов
/ 05 июля 2019

Я пытаюсь протестировать моего докладчика, который вызывает приостановленную функцию из уровня хранилища, следующим образом:

 override fun viewCreated() {
        launch {
            val hasPermission = permissionChecker.execute() //suspended function
            if (hasPermission) {
                foo()
            } else {
                view.bar()
            }
         }

Ведущий также расширяет этот интерфейс:

interface CoroutinePresenter: CoroutineScope {

val job: Job

override val coroutineContext: CoroutineContext
    get() = Dispatchers.Main + job

fun stopAllActiveJobs() {
    coroutineContext.cancelChildren()
}

И приостановленная функция определяется следующим образом:

 suspend fun execute() : Boolean = withContext(Dispatchers.IO) {
    return@withContext class.foo()
}

В приложении все работает как положено, но когда я попытался написать какой-то модульный тест, я заметил, что всякий раз, когда я вызываю кусок кода внутри launch , поток переключается, но тест не ждет выполнение. Это реализация теста:

@Test
fun `Test of Suspended Function`() = runBlocking {
    presenter.viewCreated()
    then(view).should().bar()
    ...
}

Я также добавил предлагаемую библиотеку для тестирования kotlinx-coroutines-test, но результат с ней тот же. Я также пытался следовать предложению , а также реализовывать что-то вроде this , но все же не повезло. Я думаю, что проблема заключается в фактическом создании другого потока всякий раз, когда в докладчике вызывается launch , и тест на самом деле не знает, как его ждать. Я также попытался вернуть Job и вызвать job.join(), но он не работает с NullPointerException.

Надеюсь, вы, ребята, можете мне помочь.

Ответы [ 2 ]

0 голосов
/ 09 июля 2019

Во-первых, я настоятельно рекомендую указать в качестве параметра свой coroutineContext:

  class CoroutinePresenter(coroutineContext: CoroutineContext): CoroutineScope {
         init{
               _coroutineContext = coroutineContext
          }

         override val coroutineContext: CoroutineContext
                get() = _coroutineContext

         // Your Methods

    }

В вашей реальной среде:

 @YourScope
    @Provides
    fun providesCoroutinePresenter(coroutineContext:CoroutineContext ){
        return CoroutinePresenter()
    }
    @YourScope
    @Provides
    fun providesCoroutineContext(){
        return  Dispatchers.Main + job
    }

Во время модульного теста:

    @Before
    fun setUp() {
       coroutinePresenter  CoroutinePresenter(Dispatchers.Unconfined)
    }

    @Test
    fun `Should do something`(){
         //WHEN
         coroutinePresenter.doSomething(params)
         //THEN
         do your assertions
    }

Для получения дополнительной информации, пожалуйста, проверьте Принципы твердого тела , а для этого случая D

0 голосов
/ 08 июля 2019

Я нашел решение для этого: следующий этот учебник, я настроил оба

@Before
fun setup() {
    Dispatchers.setMain(Dispatchers.Unconfined)
    ...
}
@After
fun tearDown() {
    Dispatchers.resetMain() // reset main dispatcher to the original Main dispatcher
}

И, выполнив весь запуск блока класса presenter внутри оператора runBlocking в тесте. Эта проблема была также связана с неизвестным исключением внутри приостановленной функции, которое на самом деле не было насмешливым , но оно было невидимым для моих глаз.

Теперь все работает нормально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...