Keyword: Ktor MockEngine, Unit Test
直到27日,完成KMM的测试功能放在
KMMDay27
有了基础的Mock环境,接下来我们要来Mock 网路请求.Ktor官方也有提供假的Mock引擎以便我们使用,不用自己再手动开发一个.
同样的,在gradle(shared)内我们进行Mock Engine的引用,我们是测试所以这次是放在commonTest内
//这是build.gradle.kts的soureSet内的Kotlin
val commonTest by getting {
dependencies {
...
implementation(Develop.Ktor.commonTest)
implementation(Develop.Ktor.cio)
...
}
}
而路径如下
//这是在buildSrc内的Kotlin
object Ktor{
val commonTest = "io.ktor:ktor-client-mock:${Versions.ktor}"
val cio = "io.ktor:ktor-client-cio:${Versions.ktor}"
}
有了MockEnginge後,我们来建立一个使用MockEngine的MockApi
在commonTest下建立一个Mock package,然後里面放入我们的CafeApi的Mock
//这是在commonTest下的Kotlin
class CafeApiMock(mockEngine:HttpClientEngine) : CafeApi {
companion object {
val tag = CafeApiMock::class.simpleName
}
private val client = HttpClient(mockEngine) {
install(JsonFeature) {
serializer = KotlinxSerializer()
}
}
override suspend fun fetchCafeFromApi(city: String): List<CafeResponseItem> {
return client.get("https://cafenomad.tw/api/v1.2/cafes/")
}
}
可以看到大部分都跟我们正常的CafeApiImpl相同,只是可以提供一个mockEngine来建立这个物件.
然後我们在commonTest下建立这个物件的测试流程,注意记得让commonTest去继承我们昨天写好的BaseTest,这样就能利用其中的方法建立一个给测试使用的coroutine,并且对双平台的独立测试来说没有差别,KMM会帮我们自动选择合适的实作.
//这是在commonTest底下的Kotlin语言
class CommonGreetingTest : BaseTest(){//继承了BaseTest来使用Coroutine
@Test//标注Test说明这是一个Test Case
fun KtorTest() {
}
}
然後我们可以在KtorTest内建立我们的mockEngine,来控制我们的状态与内容
val mockEngine = MockEngine { request ->//不管什麽request
respond(//都会回传这样
content = ByteReadChannel("""[{"id":"000703fe-cf8a-43c8-bd83-c90cfd61915f","name":"觉旅咖啡","address":"太阳系","city":"taipei"}]"""),
status = HttpStatusCode.OK,
headers = headersOf(HttpHeaders.ContentType, "application/json")
)
}
并且把这个mockEngine丢进去产生CafeApiMock
val apiMock = CafeApiMock(mockEngine)
最後建立回传物件以作比较
val fakeResponseItem = CafeResponseItem("000703fe-cf8a-43c8-bd83-c90cfd61915f","太阳系","觉旅咖啡","taipei")
val responseItem = listOf(fakeResponseItem)
然後在Coroutine环境下进行测试
runTest{
assertEquals(apiMock.fetchCafeFromApi("taipei"),result)
}
整份的测试内容如下
@Test
fun KtorTest() {
val mockEngine = MockEngine { request ->
respond(
content = ByteReadChannel("""[{"id":"000703fe-cf8a-43c8-bd83-c90cfd61915f","name":"觉旅咖啡","address":"太阳系","city":"taipei"}]"""),
status = HttpStatusCode.OK,
headers = headersOf(HttpHeaders.ContentType, "application/json")
)
}
val apiMock = CafeApiMock(mockEngine)
val fakeResponseItem = CafeResponseItem("000703fe-cf8a-43c8-bd83-c90cfd61915f","太阳系","觉旅咖啡","taipei")
val result = listOf(fakeResponseItem)
runTest{
assertEquals(apiMock.fetchCafeFromApi("taipei"),result)
}
}
可以点旁边的绿色三角形来跑跑看.
明天我们会来跑看看SQLDelight的测试内容
<<: Computer Architecture: Memory Hierarchy
C# BASE64 原由:厂商丢了编成 Base64 字串的东西来,接到後,要把它还原. strin...
小弟弟第一次发文, 如有不好的地方 请多包涵 (≧∀≦)ゞ 由於我是vs code 使用爱好者 所以...
今天在执行 WordPress 上的版本更新时,因为更新档案太大,出现了错误「FastCGI 处理序...
单元测试(Unit Testing) 单元测试既是一种测试工具,也是一种开发工具。现代软件开发人员通...
上一次讲到的是取得资料范围後再读取里面的内容 可是通常出题应该要随机出题 不然永远只会写到相同的题目...