Kotlin Тестирование сопрограмм с помощью Dispatchers.IO - PullRequest
3 голосов
/ 07 января 2020

Так что, возможно, было руководство по этому вопросу, но ни один из тех, что я прочитал, не решил эту проблему для меня. У меня есть структура, как показано ниже, и я пытаюсь выполнить модульное тестирование, но когда я go для тестирования, я всегда терплю неудачу, заявляя, что метод репо doSomthing() никогда не вызывался. Мое лучшее предположение, потому что я запустил новую сопрограмму в другом контексте. Как мне проверить это тогда?

Репозиторий

interface Repository {
    suspend fun doSomething(): String
}

Просмотр модели

class ViewModel(val repo: Repository) {
    val liveData = MutableLiveData<String>()
    fun doSomething {
    //Do something here
        viewModelScope.launch(Dispatchers.IO) {
            val data = repo.doSomething()
            withContext(Dispatchers.Main) {
                liveData.value = data
            }
        }
    }
}

Просмотр модели Test

class ViewModelTest {
    lateinit var viewModel: ViewModel
    lateinit var repo: Repository

    @Before
    fun setup() {
        Dispatchers.setMain(TestCoroutineDispatcher())
        repo = mock<Repository>()
        viewModel = ViewModel(repo)
    }

    @Test
    fun doSomething() = runBlockingTest {
        viewModel.doSomething()
        viewModel.liveData.test().awaitValue().assertValue {
            // assert something
        }
        verify(repo).doSomthing()
    }
}

1 Ответ

4 голосов
/ 08 января 2020

Согласно Google: enter image description here

Dispatchers должно быть введено в ваш ViewModels, чтобы вы могли правильно провести тестирование. Вы устанавливаете TestCorotutineDispatcher в качестве основного Диспетчера через Dispatchers.setMain, который контролирует MainDispatcher, но вы все еще не можете контролировать выполнение сопрограммы, запущенной через viewModelScope.launch(Dispatchers.IO).

Передача Dispatcher через конструктор гарантирует, что ваш тестовый и рабочий код использует один и тот же диспетчер.

Обычно @Rule определяется следующим образом:

  1. Переопределяет MainDispatcher с помощью Dispatchers.setMain (как вы делаете)
  2. Использует TestCoroutineDispatcher's собственный runBlockingTest() для фактического запуска теста.

Здесь - действительно хороший разговор о тестировании и сопрограммах, которые произошли на прошлогоднем Android Dev Summit.

И здесь - пример такого @Rule. (Бесстыдная вилка. Есть также примеры тестов сопрограмм на этом репо)

...