【问题标题】:Android Unit Test ViewModel Wanted but not invokedAndroid 单元测试 ViewModel 需要但未调用
【发布时间】:2020-09-30 04:57:39
【问题描述】:

我是单元测试的新手。我正在尝试对我的视图模型类进行单元测试,但我的测试失败并出现错误:

需要但未调用: toggleMovieFavorite.invoke( 电影(id=1,title=Title,overview=Overview,releaseDate=01/01/2025,posterPath=,backgroundPath=,originalLanguage=ES,originalTitle=Title,流行度=5.0,voteAverage=7.0,喜爱=false) ); -> 在 xyz.jonthn.usescases.ToggleMovieFavorite.invoke(ToggleMovieFavorite.kt:7) 实际上,与此模拟的交互为零。

这是我的测试文件

@RunWith(MockitoJUnitRunner::class)
class DetailViewModelTest {

    @get:Rule
    val rule = InstantTaskExecutorRule()

    @Mock
    lateinit var findMovieById: FindMovieById

    @Mock
    lateinit var toggleMovieFavorite: ToggleMovieFavorite

    @Mock
    lateinit var observer: Observer<Movie>

    private lateinit var vm: DetailViewModel

    @ExperimentalCoroutinesApi
    @Before
    fun setUp() {

        Dispatchers.setMain(Dispatchers.Unconfined)

        vm = DetailViewModel(1, findMovieById, toggleMovieFavorite, Dispatchers.Unconfined)
    }

    @ExperimentalCoroutinesApi
    @After
    fun tearDown() {
        Dispatchers.resetMain()
    }

    @Test
    fun `when favorite clicked, the toggleMovieFavorite use case is invoked`() {
        runBlocking {

            val movie = mockedMovie.copy(id = 1)

            whenever(findMovieById.invoke(1)).thenReturn(movie)

            whenever(toggleMovieFavorite.invoke(movie)).thenReturn(movie.copy(favorite = !movie.favorite))

            vm.movie.observeForever(observer)

            vm.onFavoriteClicked()

            verify(toggleMovieFavorite).invoke(movie)
        }
    }

    val mockedMovie = Movie(
    0,
    "Title",
    "Overview",
    "01/01/2025",
    "",
    "",
    "ES",
    "Title",
    5.0,
    7.0,
    false)
}   

这是我的 DetailViewModel:

class DetailViewModel(
private val movieId: Int, private val findMovieById: FindMovieById,
private val toggleMovieFavorite: ToggleMovieFavorite,
uiDispatcher: CoroutineDispatcher) : ScopedViewModel(uiDispatcher) {

private val _movie = MutableLiveData<Movie>()
val movie: LiveData<Movie> get() = _movie

init {
    launch {
        _movie.value = findMovieById.invoke(movieId)
    }
}

fun onFavoriteClicked() {
    launch {
        movie.value?.let {
            _movie.value = toggleMovieFavorite.invoke(it)
        }
    }
}

}

还有我的用例 ToggleMovieFavorite:

 class ToggleMovieFavorite(private val moviesRepository: MoviesRepository) {
    suspend fun invoke(movie: Movie): Movie = with(movie) {
        copy(favorite = !favorite).also { moviesRepository.update(it) }
    }
    }

非常感谢你们的帮助!!!

【问题讨论】:

    标签: android unit-testing mockito android-viewmodel


    【解决方案1】:

    我认为 mockito 不会在 viewmodel 上调用您的 init 方法,您应该将 vm 声明放在每个 @test 而不是 @Before 因为方法 findMovieById 在 init 调用,就在函数被模拟之前。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-06
      • 1970-01-01
      • 2020-08-12
      • 2023-03-15
      • 2011-01-06
      • 1970-01-01
      相关资源
      最近更新 更多