Android用例单元测试

时间:2019-12-28 16:31:42

标签: android kotlin junit android-livedata kotlin-coroutines

这是我的用例代码界面-

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(???)
        }
    }
}

1 个答案:

答案 0 :(得分:1)

这是示例代码。

我的资料库

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)
            }
        }
    }
}

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

检查

here中的CoroutinesTestRule