Skip to content

Commit

Permalink
Fix for CacheApiResponse
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffdcamp committed Nov 16, 2024
1 parent 2e27a27 commit 7a93936
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 8 deletions.
3 changes: 1 addition & 2 deletions app/src/main/kotlin/org/jdc/template/util/ext/KtorExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ suspend fun <T, E> HttpClient.executeSafelyCached(
val response = apiCall()
if (response.status == HttpStatusCode.NotModified) {
CacheApiResponse.Success(null, response.etag(), response.headers[HttpHeaders.LastModified])
}
if (response.status.isSuccess()) {
} else if (response.status.isSuccess()) {
CacheApiResponse.Success(mapSuccess(response), response.etag(), response.headers[HttpHeaders.LastModified])
} else {
val message = "Error executing service call: ${response.request.method.value} ${response.request.url} (${response.status})"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,146 @@ import io.ktor.client.plugins.resources.get
import io.ktor.http.HttpHeaders
import io.ktor.http.HttpStatusCode
import io.ktor.http.headersOf
import io.ktor.resources.Resource
import kotlinx.coroutines.test.runTest
import kotlinx.serialization.Serializable
import org.jdc.template.util.ext.executeSafelyCached
import org.junit.jupiter.api.Test

class CacheApiResponseTest {

@Test
fun `test CacheApiResponse Success`() = runTest {
fun `test CacheApiResponse Success Etag Data`() = runTest {
val mockEngine = MockEngine {
assertThat(it.headers[HttpHeaders.IfNoneMatch]).isEqualTo("abc")
respond(
content = """{"status":"success"}""",
headers = headersOf(HttpHeaders.ContentType, "application/json"),
headers = headersOf(HttpHeaders.ContentType to listOf("application/json"), HttpHeaders.ETag to listOf("def")),
status = HttpStatusCode.OK,
)
}
val client = TestHttpClientProvider.getTestClient(mockEngine)

val response: CacheApiResponse<out DtoTest, out Unit> = client.executeSafelyCached({ get(TestResource) }) { it.body() }
val response: CacheApiResponse<out DtoCacheTest, out Unit> = client.executeSafelyCached({ get(CacheTestResource) { cacheHeaders("abc", null) } }) { it.body() }

assertThat(response).isInstanceOf(CacheApiResponse.Success::class)
assertThat(response.getOrNull()).isEqualTo(DtoCacheTest("success"))
assertThat(response.getOrThrow()).isEqualTo(DtoCacheTest("success"))
assertThat(response.messageOrNull).isNull()
assertThat(response.isSuccess).isTrue()
assertThat(response.isFailure).isFalse()
assertThat(response.isError).isFalse()
assertThat(response.isException).isFalse()

response.onSuccess {
assertThat(data).isEqualTo(DtoCacheTest("success"))
assertThat(etag).isEqualTo("def")
}.onFailure {
fail("Should not be called")
}.onError {
fail("Should not be called")
}.onException {
fail("Should not be called")
}
}

@Test
fun `test CacheApiResponse Success Etag No Data`() = runTest {
val mockEngine = MockEngine {
assertThat(it.headers[HttpHeaders.IfNoneMatch]).isEqualTo("def")
respond(
content = "",
headers = headersOf(HttpHeaders.ETag to listOf("def")),
status = HttpStatusCode.NotModified,
)
}
val client = TestHttpClientProvider.getTestClient(mockEngine)

val response: CacheApiResponse<out DtoCacheTest, out Unit> = client.executeSafelyCached({ get(CacheTestResource) { cacheHeaders("def", null) } }) { it.body() }

assertThat(response).isInstanceOf(CacheApiResponse.Success::class)
assertThat(response.getOrNull()).isEqualTo(DtoTest("success"))
assertThat(response.getOrThrow()).isEqualTo(DtoTest("success"))
assertThat(response.getOrNull()).isNull()
assertThat(response.getOrThrow()).isNull()
assertThat(response.messageOrNull).isNull()
assertThat(response.isSuccess).isTrue()
assertThat(response.isFailure).isFalse()
assertThat(response.isError).isFalse()
assertThat(response.isException).isFalse()

response.onSuccess {
assertThat(data).isEqualTo(DtoTest("success"))
assertThat(data).isNull()
assertThat(etag).isEqualTo("def")
}.onFailure {
fail("Should not be called")
}.onError {
fail("Should not be called")
}.onException {
fail("Should not be called")
}
}

@Test
fun `test CacheApiResponse Success LastModified Data`() = runTest {
val mockEngine = MockEngine {
assertThat(it.headers[HttpHeaders.IfModifiedSince]).isEqualTo("abc")

respond(
content = """{"status":"success"}""",
headers = headersOf(HttpHeaders.ContentType to listOf("application/json"), HttpHeaders.LastModified to listOf("def")),
status = HttpStatusCode.OK,
)
}
val client = TestHttpClientProvider.getTestClient(mockEngine)

val response: CacheApiResponse<out DtoCacheTest, out Unit> = client.executeSafelyCached({ get(CacheTestResource) { cacheHeaders(null, "abc") } }) { it.body() }

assertThat(response).isInstanceOf(CacheApiResponse.Success::class)
assertThat(response.getOrNull()).isEqualTo(DtoCacheTest("success"))
assertThat(response.getOrThrow()).isEqualTo(DtoCacheTest("success"))
assertThat(response.messageOrNull).isNull()
assertThat(response.isSuccess).isTrue()
assertThat(response.isFailure).isFalse()
assertThat(response.isError).isFalse()
assertThat(response.isException).isFalse()

response.onSuccess {
assertThat(data).isEqualTo(DtoCacheTest("success"))
assertThat(lastModified).isEqualTo("def")
}.onFailure {
fail("Should not be called")
}.onError {
fail("Should not be called")
}.onException {
fail("Should not be called")
}
}

@Test
fun `test CacheApiResponse Success LastModified No Data`() = runTest {
val mockEngine = MockEngine {
assertThat(it.headers[HttpHeaders.IfModifiedSince]).isEqualTo("def")
respond(
content = "",
headers = headersOf(HttpHeaders.LastModified to listOf("def")),
status = HttpStatusCode.NotModified,
)
}
val client = TestHttpClientProvider.getTestClient(mockEngine)

val response: CacheApiResponse<out DtoCacheTest, out Unit> = client.executeSafelyCached({ get(CacheTestResource) { cacheHeaders(null, "def") } }) { it.body() }

assertThat(response).isInstanceOf(CacheApiResponse.Success::class)
assertThat(response.getOrNull()).isNull()
assertThat(response.getOrThrow()).isNull()
assertThat(response.messageOrNull).isNull()
assertThat(response.isSuccess).isTrue()
assertThat(response.isFailure).isFalse()
assertThat(response.isError).isFalse()
assertThat(response.isException).isFalse()

response.onSuccess {
assertThat(data).isNull()
assertThat(lastModified).isEqualTo("def")
}.onFailure {
fail("Should not be called")
}.onError {
Expand Down Expand Up @@ -333,3 +443,8 @@ class CacheApiResponseTest {

}
}

@Serializable
private data class DtoCacheTest( val status: String)
@Resource("test")
private object CacheTestResource

0 comments on commit 7a93936

Please sign in to comment.