mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-14 19:57:04 +05:30
api: use retrofit-mock for tests
This commit is contained in:
parent
23ce5a489e
commit
ad456c6141
5 changed files with 64 additions and 88 deletions
|
@ -12,6 +12,6 @@ dependencies {
|
||||||
testImplementation(libs.kotlinx.serialization.json)
|
testImplementation(libs.kotlinx.serialization.json)
|
||||||
testImplementation(libs.kotlin.coroutines.core)
|
testImplementation(libs.kotlin.coroutines.core)
|
||||||
testImplementation(kotlin("test-junit"))
|
testImplementation(kotlin("test-junit"))
|
||||||
testImplementation(libs.retrofit.kotlinxSerializationConverter) { isTransitive = false }
|
testImplementation(libs.retrofit.kotlinxSerializationConverter)
|
||||||
testImplementation(libs.testing.mockWebServer)
|
testImplementation(libs.retrofit.mock)
|
||||||
}
|
}
|
||||||
|
|
32
api/src/test/kotlin/dev/msfjarvis/claw/api/ApiTest.kt
Normal file
32
api/src/test/kotlin/dev/msfjarvis/claw/api/ApiTest.kt
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package dev.msfjarvis.claw.api
|
||||||
|
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.mock.MockRetrofit
|
||||||
|
import retrofit2.mock.create
|
||||||
|
|
||||||
|
class ApiTest {
|
||||||
|
private val retrofit = Retrofit.Builder().baseUrl(LobstersApi.BASE_URL).build()
|
||||||
|
private val api = MockRetrofit.Builder(retrofit).build().create<LobstersApi>().let(::FakeApi)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `api gets correct number of items`() = runBlocking {
|
||||||
|
val posts = api.getHottestPosts(1)
|
||||||
|
assertEquals(25, posts.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `posts with no urls`() = runBlocking {
|
||||||
|
val posts = api.getHottestPosts(1)
|
||||||
|
val commentsOnlyPosts = posts.asSequence().filter { it.url.isEmpty() }.toSet()
|
||||||
|
assertEquals(2, commentsOnlyPosts.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `post details with comments`() = runBlocking {
|
||||||
|
val postDetails = api.getPostDetails("d9ucpe")
|
||||||
|
assertEquals(7, postDetails.comments.size)
|
||||||
|
}
|
||||||
|
}
|
27
api/src/test/kotlin/dev/msfjarvis/claw/api/FakeApi.kt
Normal file
27
api/src/test/kotlin/dev/msfjarvis/claw/api/FakeApi.kt
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package dev.msfjarvis.claw.api
|
||||||
|
|
||||||
|
import dev.msfjarvis.claw.model.LobstersPost
|
||||||
|
import dev.msfjarvis.claw.model.LobstersPostDetails
|
||||||
|
import dev.msfjarvis.claw.util.TestUtils.getJson
|
||||||
|
import kotlinx.serialization.decodeFromString
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import retrofit2.mock.BehaviorDelegate
|
||||||
|
|
||||||
|
class FakeApi(private val delegate: BehaviorDelegate<LobstersApi>) : LobstersApi {
|
||||||
|
private val json = Json { ignoreUnknownKeys = true }
|
||||||
|
private val hottest: List<LobstersPost> = json.decodeFromString(getJson("hottest.json"))
|
||||||
|
private val postDetails: LobstersPostDetails =
|
||||||
|
json.decodeFromString(getJson("post_details_d9ucpe.json"))
|
||||||
|
|
||||||
|
override suspend fun getHottestPosts(page: Int): List<LobstersPost> {
|
||||||
|
return delegate.returningResponse(hottest).getHottestPosts(page)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getNewestPosts(page: Int): List<LobstersPost> {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getPostDetails(postId: String): LobstersPostDetails {
|
||||||
|
return delegate.returningResponse(postDetails).getPostDetails(postId)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,84 +0,0 @@
|
||||||
package dev.msfjarvis.claw.api
|
|
||||||
|
|
||||||
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
|
|
||||||
import dev.msfjarvis.claw.util.TestUtils
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
import kotlin.test.fail
|
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
|
||||||
import kotlinx.serialization.json.Json
|
|
||||||
import mockwebserver3.Dispatcher
|
|
||||||
import mockwebserver3.MockResponse
|
|
||||||
import mockwebserver3.MockWebServer
|
|
||||||
import mockwebserver3.RecordedRequest
|
|
||||||
import okhttp3.MediaType.Companion.toMediaType
|
|
||||||
import okhttp3.OkHttpClient
|
|
||||||
import org.junit.AfterClass
|
|
||||||
import org.junit.BeforeClass
|
|
||||||
import retrofit2.Retrofit
|
|
||||||
import retrofit2.create
|
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
|
||||||
class LobstersApiTest {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private val contentType = "application/json".toMediaType()
|
|
||||||
private val webServer = MockWebServer()
|
|
||||||
private val okHttp = OkHttpClient.Builder().build()
|
|
||||||
private val json = Json { ignoreUnknownKeys = true }
|
|
||||||
private val retrofit =
|
|
||||||
Retrofit.Builder()
|
|
||||||
.client(okHttp)
|
|
||||||
.baseUrl("http://localhost:8080/")
|
|
||||||
.addConverterFactory(json.asConverterFactory(contentType))
|
|
||||||
.build()
|
|
||||||
private val apiClient = retrofit.create<LobstersApi>()
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@BeforeClass
|
|
||||||
fun setUp() {
|
|
||||||
webServer.start(8080)
|
|
||||||
webServer.dispatcher =
|
|
||||||
object : Dispatcher() {
|
|
||||||
override fun dispatch(request: RecordedRequest): MockResponse {
|
|
||||||
val path = requireNotNull(request.path)
|
|
||||||
return when {
|
|
||||||
path.startsWith("/hottest") ->
|
|
||||||
MockResponse().setBody(TestUtils.getJson("hottest.json")).setResponseCode(200)
|
|
||||||
path.startsWith("/s/") ->
|
|
||||||
MockResponse()
|
|
||||||
.setBody(TestUtils.getJson("post_details_d9ucpe.json"))
|
|
||||||
.setResponseCode(200)
|
|
||||||
else -> fail("'$path' unexpected")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
@AfterClass
|
|
||||||
fun tearDown() {
|
|
||||||
webServer.shutdown()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `api gets correct number of items`() = runBlocking {
|
|
||||||
val posts = apiClient.getHottestPosts(1)
|
|
||||||
assertEquals(25, posts.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `posts with no urls`() = runBlocking {
|
|
||||||
val posts = apiClient.getHottestPosts(1)
|
|
||||||
val commentsOnlyPosts = posts.asSequence().filter { it.url.isEmpty() }.toSet()
|
|
||||||
assertEquals(2, commentsOnlyPosts.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `post details with comments`() = runBlocking {
|
|
||||||
val postDetails = apiClient.getPostDetails("d9ucpe")
|
|
||||||
assertEquals(7, postDetails.comments.size)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,6 +6,7 @@ dagger = "2.41"
|
||||||
hilt = "1.0.0"
|
hilt = "1.0.0"
|
||||||
kotlin = "1.6.10"
|
kotlin = "1.6.10"
|
||||||
material_motion = "0.8.4"
|
material_motion = "0.8.4"
|
||||||
|
retrofit = "2.9.0"
|
||||||
richtext = "0.11.0"
|
richtext = "0.11.0"
|
||||||
serialization = "1.3.2"
|
serialization = "1.3.2"
|
||||||
sqldelight = "2.0.0-alpha02"
|
sqldelight = "2.0.0-alpha02"
|
||||||
|
@ -52,13 +53,13 @@ multiplatform-paging = "io.github.kuuuurt:multiplatform-paging:0.4.7"
|
||||||
napier = "io.github.aakira:napier:2.5.0"
|
napier = "io.github.aakira:napier:2.5.0"
|
||||||
r8 = "com.android.tools:r8:3.3.28"
|
r8 = "com.android.tools:r8:3.3.28"
|
||||||
retrofit-kotlinxSerializationConverter = "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
|
retrofit-kotlinxSerializationConverter = "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
|
||||||
retrofit-lib = "com.squareup.retrofit2:retrofit:2.9.0"
|
retrofit-lib = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
|
||||||
|
retrofit-mock = { module = "com.squareup.retrofit2:retrofit-mock", version.ref = "retrofit" }
|
||||||
svg-transcoder = "org.pushing-pixels:aurora-tools-svg-transcoder-gradle-plugin:1.1.0"
|
svg-transcoder = "org.pushing-pixels:aurora-tools-svg-transcoder-gradle-plugin:1.1.0"
|
||||||
sqldelight-androidDriver = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" }
|
sqldelight-androidDriver = { module = "app.cash.sqldelight:android-driver", version.ref = "sqldelight" }
|
||||||
sqldelight-extensions-coroutines = { module = "app.cash.sqldelight:coroutines-extensions-jvm", version.ref = "sqldelight" }
|
sqldelight-extensions-coroutines = { module = "app.cash.sqldelight:coroutines-extensions-jvm", version.ref = "sqldelight" }
|
||||||
sqldelight-jvmDriver = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqldelight" }
|
sqldelight-jvmDriver = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqldelight" }
|
||||||
sqldelight-primitiveAdapters = { module = "app.cash.sqldelight:primitive-adapters", version.ref = "sqldelight" }
|
sqldelight-primitiveAdapters = { module = "app.cash.sqldelight:primitive-adapters", version.ref = "sqldelight" }
|
||||||
testing-mockWebServer = "com.squareup.okhttp3:mockwebserver3-junit4:5.0.0-alpha.7"
|
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
compose = "org.jetbrains.compose:1.1.1"
|
compose = "org.jetbrains.compose:1.1.1"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue