Как проверить вызов Kotlin приостановки в Android с помощью MockK? - PullRequest
0 голосов
/ 06 августа 2020

Я пробую свои силы на TDD с приложением Android. Я пишу это в Kotlin, и из-за этого я обратился к MockK для тестирования, но есть одна вещь (на данный момент), которую я не смог узнать, как это сделать: протестировать вызов приостановки.

Я написал тест для значения LiveData в ViewModel и заставил его работать. Однако, когда я добавил сопрограммы в микс, я начал получать сообщение «Method getMainLooper not mocked».

Вот мой код:

ToDoListViewModelTest.kt

class ToDoListViewModelTest {

    @get:Rule
    var instantExecutorRule = InstantTaskExecutorRule()

    @MockK
    private lateinit var toDoListLiveDataObserver: Observer<List<ToDoItem>>

    @MockK
    private lateinit var getToDoItemsUseCase: GetToDoItemsUseCase

    @Before
    fun setUp() {
        MockKAnnotations.init(this)
        every { toDoListLiveDataObserver.onChanged(any()) } answers { nothing }
    }

    @Test
    fun toDoList_listItems_noItems() = runBlocking {

        coEvery { getToDoItemsUseCase() } coAnswers { emptyList<ToDoItem>() }

        val toDoListViewModel = ToDoListViewModel(getToDoItemsUseCase)
        toDoListViewModel.toDoItemList.observeForever(toDoListLiveDataObserver)

        toDoListViewModel.updateItemList()

        assertEquals(0, toDoListViewModel.toDoItemList.value?.size)
    }
}

ToDoListViewModel.kt

class ToDoListViewModel(private val getToDoItemsUseCase: GetToDoItemsUseCase) : ViewModel() {

    private val _toDoItemList: MutableLiveData<List<ToDoItem>> = MutableLiveData()
    val toDoItemList : LiveData<List<ToDoItem>> = _toDoItemList

    fun updateItemList() {
        viewModelScope.launch(Dispatchers.IO) {
            _toDoItemList.value = getToDoItemsUseCase()
        }
    }
}

GetToDoItemsUseCase.kt

class GetToDoItemsUseCase {
    suspend operator fun invoke(): List<ToDoItem> {
        return listOf()
    }
}

Что я пробовал:

  • Добавление «@RunWith (BlockJUnit4ClassRunner :: class)»: без изменений
  • Добавление «testOptions {unitTests.returnDefaultValues ​​= true}» в файл Gradle: ошибка Looper исчезает, но значение, поступающее из LiveData, равно NULL, вместо пустого списка, указанного в вызове coEvery.
  • Вызов «Dispatchers.setMain (newSingleThreadContext (« UI Thread »))»: То же, что и в предыдущем случае, получение null из LiveData.

Я не очень опытен в тестировании, и у меня закончились варианты. Я чувствую, что мне определенно нужна помощь сообщества;)

Кроме того, если по какой-то причине мои настройки не подходят (следует использовать что-то отличное от MockK или какой-либо другой среды тестирования ...), пожалуйста, прокомментируйте и это. Мне еще многое предстоит узнать об этом.

1 Ответ

0 голосов
/ 21 августа 2020

Использовать postValue _toDoItemList.postValue(getToDoItemsUseCase())

На основе документации:

setValue () :

Устанавливает значение. Если есть активные наблюдатели, значение будет отправлено им. Этот метод должен вызываться из основного потока.

postValue () :

Отправляет задачу в основной поток, чтобы установить заданное значение . Если вы вызываете этот метод несколько раз до того, как основной поток выполнит опубликованную задачу, будет отправлено только последнее значение.

...