Skip to content

Commit f2e772f

Browse files
committed
test: CacheGithubLanguageColorApiDecoratorTest
1 parent 87ec94a commit f2e772f

File tree

2 files changed

+135
-3
lines changed

2 files changed

+135
-3
lines changed

shared/src/commonMain/kotlin/com/hoc081098/github_search_kmm/data/remote/KtorGithubLanguageColorApi.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import io.ktor.client.request.get
1111
import io.ktor.http.Url
1212
import kotlinx.coroutines.withContext
1313

14-
typealias ColorResponseType = Map<String, Map<String, String?>>
14+
typealias ColorsResponseType = Map<String, Map<String, String?>>
1515

1616
internal open class KtorGithubLanguageColorApi(
1717
private val url: Url,
@@ -23,12 +23,12 @@ internal open class KtorGithubLanguageColorApi(
2323
.catch {
2424
httpClient
2525
.get(url)
26-
.body<ColorResponseType>()
26+
.body<ColorsResponseType>()
2727
}
2828
.flatMap { it.toColors() }
2929
}
3030

31-
private fun ColorResponseType.toColors(): Either<IllegalStateException, Map<String, ArgbColor>> {
31+
private fun ColorsResponseType.toColors(): Either<IllegalStateException, Map<String, ArgbColor>> {
3232
return mapNotNull { (k, v) ->
3333
v["color"]?.let {
3434
k to it
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package com.hoc081098.github_search_kmm.data.remote
2+
3+
import arrow.core.left
4+
import arrow.core.right
5+
import com.hoc081098.github_search_kmm.TestAntilog
6+
import com.hoc081098.github_search_kmm.domain.model.ArgbColor
7+
import com.hoc081098.github_search_kmm.getOrThrow
8+
import io.github.aakira.napier.Napier
9+
import io.mockative.given
10+
import io.mockative.mock
11+
import io.mockative.once
12+
import io.mockative.twice
13+
import io.mockative.verify
14+
import kotlin.test.AfterTest
15+
import kotlin.test.BeforeTest
16+
import kotlin.test.Test
17+
import kotlin.test.assertEquals
18+
import kotlinx.coroutines.async
19+
import kotlinx.coroutines.awaitAll
20+
import kotlinx.coroutines.delay
21+
import kotlinx.coroutines.test.runTest
22+
23+
class CacheGithubLanguageColorApiDecoratorTest {
24+
private val antilog = TestAntilog()
25+
26+
private lateinit var cacheGithubLanguageColorApiDecorator: CacheGithubLanguageColorApiDecorator
27+
private lateinit var decoratee: GithubLanguageColorApi
28+
29+
@BeforeTest
30+
fun setup() {
31+
Napier.base(antilog)
32+
33+
decoratee = mock(GithubLanguageColorApi::class)
34+
cacheGithubLanguageColorApiDecorator = CacheGithubLanguageColorApiDecorator(
35+
decoratee = decoratee
36+
)
37+
}
38+
39+
@AfterTest
40+
fun teardown() {
41+
verify(decoratee).hasNoUnverifiedExpectations()
42+
verify(decoratee).hasNoUnmetExpectations()
43+
44+
Napier.takeLogarithm(antilog)
45+
}
46+
47+
@Test
48+
fun `cache Right value WHEN decoratee_getColors returns a Right value`() = runTest {
49+
val right = mapOf("kotlin" to ArgbColor.parse("#F18E33").getOrThrow).right()
50+
51+
given(decoratee)
52+
.invocation { toString() }
53+
.thenReturn("GithubLanguageColorApi")
54+
55+
given(decoratee)
56+
.coroutine { getColors() }
57+
.then {
58+
delay(100)
59+
right
60+
}
61+
62+
(
63+
(0..20)
64+
.map { v ->
65+
async {
66+
if (v <= 10) {
67+
delay(200)
68+
}
69+
cacheGithubLanguageColorApiDecorator.getColors()
70+
}
71+
}
72+
.awaitAll() + cacheGithubLanguageColorApiDecorator.getColors()
73+
)
74+
.forEach { assertEquals(right, it) }
75+
76+
verify(decoratee)
77+
.coroutine { getColors() }
78+
.wasInvoked(exactly = once)
79+
verify(decoratee)
80+
.invocation { toString() }
81+
.wasInvoked()
82+
}
83+
84+
@Test
85+
fun `cache Right value WHEN decoratee_getColors returns a Left value`() = runTest {
86+
val left = RuntimeException().left()
87+
val right = mapOf("kotlin" to ArgbColor.parse("#F18E33").getOrThrow).right()
88+
89+
var call = 0
90+
91+
given(decoratee)
92+
.invocation { toString() }
93+
.thenReturn("GithubLanguageColorApi")
94+
95+
given(decoratee)
96+
.coroutine { getColors() }
97+
.then {
98+
delay(100)
99+
100+
when (call++) {
101+
0 -> left
102+
1 -> right
103+
else -> error("Should not be called")
104+
}
105+
}
106+
107+
val eithers = (
108+
(0..20)
109+
.map { v ->
110+
async {
111+
if (v in 10..15) {
112+
delay(200)
113+
}
114+
cacheGithubLanguageColorApiDecorator.getColors()
115+
}
116+
}
117+
.awaitAll() + cacheGithubLanguageColorApiDecorator.getColors()
118+
)
119+
120+
assertEquals(
121+
listOf(left) + (1..21).map { right },
122+
eithers
123+
)
124+
125+
verify(decoratee)
126+
.coroutine { getColors() }
127+
.wasInvoked(exactly = twice)
128+
verify(decoratee)
129+
.invocation { toString() }
130+
.wasInvoked()
131+
}
132+
}

0 commit comments

Comments
 (0)