Android 用例单元测试

Android use case unit test

这是我的用例代码接口 -

interface ItemUseCase {

     fun performItemAction(action: ItemAction): LiveData<Result>

}

这是实现 -

class ItemUseCaseImpl(
    private val dataRepository: DataRepository
) : ItemUseCase {

    override fun performItemAction(action: ItemAction) = liveData {
        emit(Result.Loading)
        emit(dataRepository.performDataAction(action))
    }
}

我是编写单元测试的新手。所以我需要帮助 -

1) 我可以在我的用例中测试什么

2) 我也尝试在下面编写一些单元测试,但如何将 LiveData 放入 thenReturn

这是我的单元测试代码 -

class ItemUseCaseImplTest {

    @Rule
    @JvmField
    val rule = InstantTaskExecutorRule()

    @Mock
    private lateinit var itemUseCase: ItemUseCase

    @Mock
    private lateinit var dataRepository: DataRepository

    @Before
    fun setUp() {
        dataRepository = mockk()
        itemUseCase = ItemUseCaseImpl(dataRepository)
    }

    @After
    fun tearDown() {
    }

    @Test
    fun performItemAction() {
        runBlocking {
            whenever(
                itemUseCase.performItemAction(
                    ItemAction.RegisterUser(“xyz”, "20")
                )
            )
                .thenReturn(???)
        }
    }
}

这是示例代码。

我的资料库

interface RepositoryInterface {
    suspend fun performAPI(): Result<Map<String, Top100Item>>
}

class Repository(private val service: GameService) : RepositoryInterface {
    override suspend fun performAPI(): Result<Map<String, Top100Item>> = try {
        Result.Success(service.getTop100())
    } catch (exception: Exception) {
        Result.Error(null, exception)
    }
}

我的 MainViewModel 从 ViewModel 扩展并实现 GameUserInterface

interface GameUserCase {
    fun getGames(): LiveData<Result<Map<String, Top100Item>>>
}

class MainViewModel(
    private val repository: RepositoryInterface,
    private val dispatcher: CoroutineDispatcher = Dispatchers.IO,
    private val loadingResource: Result<Map<String, Top100Item>> = Result.Loading(null)
) : ViewModel(), GameUserCase {

    override fun getGames(): LiveData<Result<Map<String, Top100Item>>> = liveData(dispatcher) {
        emit(loadingResource)
        emit(repository.performAPI())
    }
}

下面是测试 MainViewModel 的测试示例:

@ExperimentalCoroutinesApi
@RunWith(MockitoJUnitRunner::class)
class MainViewModelTest {

    @Mock
    private lateinit var repository: RepositoryInterface

    private lateinit var viewModel: MainViewModel

    private val testDispatcher = TestCoroutineDispatcher()

    @ExperimentalCoroutinesApi
    @get:Rule
    var coroutinesTestRule = CoroutinesTestRule()

    @Rule
    @JvmField
    var rule: TestRule = InstantTaskExecutorRule()

    private val loading: Result.Loading<Map<String, Top100Item>> = Result.Loading(null)

    private val mockItem = Top100Item(appId = 30, name = "name", developer = "developer", publisher = "publisher")

    @Before
    fun setup() {
        viewModel = MainViewModel(repository, testDispatcher, loading)
    }

    @Test
    fun testGetDataSuccess() {
        testDispatcher.pauseDispatcher()
        val map = mapOf("30" to mockItem)
        val successResult = Result.Success(map)
        runBlockingTest {
            `when`(repository.performAPI()).thenReturn(successResult)

            val result = viewModel.getGames()
            testDispatcher.resumeDispatcher()

            // verify loading
            assertThat(result.getOrAwaitValue()).isEqualTo(loading)

            result.observeForTesting {
                testDispatcher.resumeDispatcher()
                assertThat(result.value).isEqualTo(successResult)
            }
        }
    }
}

在测试class中,我会在调用getGames时验证响应是否成功,所以数据会响应Result.Success。对于 getOrAwaitValueobserveForTesting 方法,您可以从 architecture-components-samples

中查看

CoroutinesTestRule 来自 here