Jon*_*han 2 junit android unit-testing kotlin android-studio
我在单元测试时收到此错误:“LiveData 值从未设置。”
我正在尝试测试我的视图模型的 getStudents() 方法,如下所示:
学生视图模型:
@HiltViewModel
class StudentViewModel @Inject constructor(
private val getStudentsUseCase: GetStudentsUseCase
) : ViewModel() {
private val _studentLD = MutableLiveData<List<Student>>()
val studentLD: LiveData<List<Student>> = _studentLD
private val _errorLD = MutableLiveData<String>()
val errorLD: LiveData<String> = _errorLD
fun getStudents() {
viewModelScope.launch {
var result = getStudentsUseCase.execute()
result.onSuccess {
_studentLD.value = it
}.onFailure {
_errorLD.value = it.message.toString()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
学生视图模型测试:
@OptIn(ExperimentalCoroutinesApi::class)
class StudentViewModelTest {
private lateinit var viewModel: StudentViewModel
@get:Rule
var instantExecutorRule = InstantTaskExecutorRule()
@get:Rule
var mainCoroutineRule = MainCoroutineRule()
@Mock
private lateinit var getStudentsUseCase: GetStudentsUseCase
private var studentList = listOf(
Student("Max", "122d"),
Student("Steven", "012s")
)
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
viewModel = StudentViewModel(getStudentsUseCase)
}
@Test
fun getStudentsSuccess() = runTest {
Mockito.`when`(getStudentsUseCase.execute()).thenReturn(Result.success(studentList))
viewModel.getStudents()
val value = viewModel.studentLD.getOrAwaitValueTest()
assertEquals(value, studentList)
}
}
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?我还有一个 LiveDataTest 类,其中定义了 getOrAwaitValueTest() 方法。先感谢您
编辑:另外, getOrAwaitValueTest() 方法在这里定义如下:
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
fun <T> LiveData<T>.getOrAwaitValueTest(
time: Long = 2,
timeUnit: TimeUnit = TimeUnit.SECONDS,
afterObserve: () -> Unit = {}
): T {
var data: T? = null
val latch = CountDownLatch(1)
val observer = object : Observer<T> {
override fun onChanged(o: T?) {
data = o
latch.countDown()
this@getOrAwaitValueTest.removeObserver(this)
}
}
this.observeForever(observer)
try {
afterObserve.invoke()
// Don't wait indefinitely if the LiveData is not set.
if (!latch.await(time, timeUnit)) {
throw TimeoutException("LiveData value was never set.")
}
} finally {
this.removeObserver(observer)
}
@Suppress("UNCHECKED_CAST")
return data as T
}
Run Code Online (Sandbox Code Playgroud)
我找到了一个解决方案:为了使其正常工作,您需要添加 advanceUntilIdle() 方法。
立即执行所有挂起的任务并将虚拟时钟时间提前到最后的延迟。如果由于虚拟时间提前而安排新任务,它们将在 advanceUntilIdle 返回之前执行。
@Test
fun getStudentsSuccess() = runTest {
Mockito.`when`(getStudentsUseCase.execute()).thenReturn(Result.success(studentList))
viewModel.getStudents()
advanceUntilIdle()
val value = viewModel.studentLD.getOrAwaitValueTest()
assertEquals(value, studentList)
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4470 次 |
| 最近记录: |