mockito 如何使用MockK测试暂停功能?

bpzcxfmw  于 2022-11-08  发布在  其他
关注(0)|答案(2)|浏览(189)

我正在为我的数据仓库层编写一个单元测试,它只调用一个接口。我正在使用Kotlin、协程和MockK进行单元测试。在MockK中,我如何验证我调用了apiServiceInterface.getDataFromApi()并且只发生了一次?我应该把代码放在runBlocking中吗?
这是我的代码:
单元测试

import com.example.breakingbad.api.ApiServiceInterface
import com.example.breakingbad.data.DataRepository
import io.mockk.impl.annotations.InjectMockKs
import io.mockk.impl.annotations.MockK
import io.mockk.verify
import org.junit.Test

资料档案库

class DataRepositoryTest {
    @MockK
    private lateinit var apiServiceInterface: ApiServiceInterface

    @InjectMockKs
    private lateinit var dataRepository: DataRepository

    @Test
    fun getCharacters() {
            val respose = dataRepository.getCharacters()
            verify { apiServiceInterface.getDataFromApi() }
    }
}

    class DataRepository @Inject constructor(
    private val apiServiceInterface: ApiServiceInterface
) {
    suspend fun getCharacters(): Result<ArrayList<Character>> = kotlin.runCatching{
        apiServiceInterface.getDataFromApi()
    }
}

接口

interface ApiServiceInterface {
    @GET("api/characters")
    suspend fun getDataFromApi(): ArrayList<Character>
}
iqjalb3h

iqjalb3h1#

我认为你应该更喜欢使用runTest而不是runBlockingrunBlockingTest

  1. runBlocking允许你通过阻塞一个新的协程来调用suspend函数,并且它阻塞当前线程直到它完成。
  2. X1 M4 N1 X将跳过任何延迟立即执行挂起函数并立即进入协程块
    自kotlinx.coroutines 1.6.0发行版起,由于迁移指南中列出的这些原因,runBlockingTest被弃用,而runTest被取代。
  3. runTest()将自动跳过对delay()的调用并处理未捕获的异常。与runBlockingTest()不同的是,它将等待异步回调来处理某些代码在未与测试模块集成的调度程序中运行的情况。
    我希望这能回答你的问题,从这三个中选择什么来测试你的暂停功能。你的代码看起来像这样-:
@Test
fun getCharacters() = runTest {
    val response = dataRepository.getCharacters()

    coVerify { apiServiceInterface.getDataFromApi() }
}

还请注意,正如David在上面提到的,因为getDataFromApi()也是异步/挂起函数,所以您将不得不使用coVerify而不是verify来模拟相同的功能。

2ledvvac

2ledvvac2#

是的,您应该将dataRepository.getCharacters()调用放在runBlocking中。
并且应将verify替换为coVerify
最后,测试应该如下所示:

@Test
fun getCharacters() {
    val respose = runBlocking { dataRepository.getCharacters() }

    coVerify { apiServiceInterface.getDataFromApi() }
}

此外,由于您希望验证它只发生过一次,因此需要使用 exactly 参数coVerify(exactly = 1)调用coVerify

相关问题