test: add unit tests for MatchRemoteDataSourceImpl
This commit is contained in:
parent
7f5f0dcf54
commit
e53d0c0903
4 changed files with 179 additions and 17 deletions
|
@ -75,12 +75,15 @@ dependencies {
|
||||||
implementation(libs.coil.network)
|
implementation(libs.coil.network)
|
||||||
ksp(libs.hilt.android.compiler)
|
ksp(libs.hilt.android.compiler)
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
|
testImplementation(libs.kotlinx.coroutines.test)
|
||||||
|
testImplementation(libs.mockk)
|
||||||
androidTestImplementation(libs.androidx.junit)
|
androidTestImplementation(libs.androidx.junit)
|
||||||
androidTestImplementation(libs.androidx.espresso.core)
|
androidTestImplementation(libs.androidx.espresso.core)
|
||||||
androidTestImplementation(platform(libs.androidx.compose.bom))
|
androidTestImplementation(platform(libs.androidx.compose.bom))
|
||||||
androidTestImplementation(libs.androidx.ui.test.junit4)
|
androidTestImplementation(libs.androidx.ui.test.junit4)
|
||||||
debugImplementation(libs.androidx.ui.tooling)
|
debugImplementation(libs.androidx.ui.tooling)
|
||||||
debugImplementation(libs.androidx.ui.test.manifest)
|
debugImplementation(libs.androidx.ui.test.manifest)
|
||||||
|
testImplementation(kotlin("test"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSecret(key: String): String {
|
fun getSecret(key: String): String {
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
package xyz.leomurca.csgomatches
|
|
||||||
|
|
||||||
import org.junit.Test
|
|
||||||
|
|
||||||
import org.junit.Assert.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Example local unit test, which will execute on the development machine (host).
|
|
||||||
*
|
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
|
||||||
*/
|
|
||||||
class ExampleUnitTest {
|
|
||||||
@Test
|
|
||||||
fun addition_isCorrect() {
|
|
||||||
assertEquals(4, 2 + 2)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
package xyz.leomurca.csgomatches.data.remote
|
||||||
|
|
||||||
|
import io.mockk.MockKAnnotations
|
||||||
|
import io.mockk.coEvery
|
||||||
|
import io.mockk.coVerify
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.impl.annotations.InjectMockKs
|
||||||
|
import io.mockk.impl.annotations.RelaxedMockK
|
||||||
|
import io.mockk.mockk
|
||||||
|
import junit.framework.TestCase.assertTrue
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||||
|
import kotlinx.coroutines.test.resetMain
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import kotlinx.coroutines.test.setMain
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import retrofit2.Response
|
||||||
|
import xyz.leomurca.csgomatches.data.model.ErrorDto
|
||||||
|
import xyz.leomurca.csgomatches.data.model.LeagueDto
|
||||||
|
import xyz.leomurca.csgomatches.data.model.MatchDto
|
||||||
|
import xyz.leomurca.csgomatches.data.model.SerieDto
|
||||||
|
import xyz.leomurca.csgomatches.data.model.TeamDetailsDto
|
||||||
|
import xyz.leomurca.csgomatches.domain.model.Resource
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
class MatchRemoteDataSourceImplTest {
|
||||||
|
|
||||||
|
@RelaxedMockK
|
||||||
|
private lateinit var api: MatchesApiService
|
||||||
|
|
||||||
|
@RelaxedMockK
|
||||||
|
private lateinit var json: Json
|
||||||
|
|
||||||
|
@InjectMockKs
|
||||||
|
private lateinit var dataSource: MatchRemoteDataSourceImpl
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
MockKAnnotations.init(this)
|
||||||
|
Dispatchers.setMain(StandardTestDispatcher())
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
Dispatchers.resetMain()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `upcomingMatches - response is successful - return Resource Success with matches`() =
|
||||||
|
runTest {
|
||||||
|
// Arrange
|
||||||
|
val matches = listOf(MATCH_DTO)
|
||||||
|
coEvery { api.upcomingMatches() } returns Response.success(matches)
|
||||||
|
|
||||||
|
// Act
|
||||||
|
val result = dataSource.upcomingMatches()
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
coVerify(exactly = 1) {
|
||||||
|
api.upcomingMatches("running, not_started", false, "begin_at")
|
||||||
|
}
|
||||||
|
assertTrue(result is Resource.Success)
|
||||||
|
assertEquals(matches, (result as Resource.Success).data)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `upcomingMatches - response is an error - return api error with error body`() = runTest {
|
||||||
|
// Arrange
|
||||||
|
val errorDto = ErrorDto(message = "API failure")
|
||||||
|
|
||||||
|
coEvery { api.upcomingMatches() } returns mockk(relaxed = true) {
|
||||||
|
every { isSuccessful } returns false
|
||||||
|
}
|
||||||
|
every { json.decodeFromString<ErrorDto>(any()) } returns errorDto
|
||||||
|
|
||||||
|
// Act
|
||||||
|
val result = dataSource.upcomingMatches()
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertTrue(result is Resource.Error)
|
||||||
|
assertEquals("API failure", (result as Resource.Error).message)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `upcomingMatches - response is an RuntimeException - returns Resource Error`() = runTest {
|
||||||
|
// Arrange
|
||||||
|
coEvery { api.upcomingMatches() } throws RuntimeException("Network error")
|
||||||
|
|
||||||
|
// Act
|
||||||
|
val result = dataSource.upcomingMatches()
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertTrue(result is Resource.Error)
|
||||||
|
assertEquals("Network error", (result as Resource.Error).message)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `teamDetails - response is successful - returns Resource Success`() = runTest {
|
||||||
|
// Arrange
|
||||||
|
val teamDetails = listOf(TEAM_DETAILS_DTO)
|
||||||
|
coEvery { api.teamDetails("123") } returns Response.success(teamDetails)
|
||||||
|
|
||||||
|
// Act
|
||||||
|
val result = dataSource.teamDetails("123")
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertTrue(result is Resource.Success)
|
||||||
|
assertEquals(teamDetails, (result as Resource.Success).data)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `teamDetails - response is an error - returns Resource Error`() = runTest {
|
||||||
|
// Arrange
|
||||||
|
val errorDto = ErrorDto(message = "Team not found")
|
||||||
|
|
||||||
|
coEvery { api.teamDetails("456") } returns mockk(relaxed = true) {
|
||||||
|
every { isSuccessful } returns false
|
||||||
|
}
|
||||||
|
every { json.decodeFromString<ErrorDto>(any()) } returns errorDto
|
||||||
|
|
||||||
|
// Act
|
||||||
|
val result = dataSource.teamDetails("456")
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertTrue(result is Resource.Error)
|
||||||
|
assertEquals("Team not found", (result as Resource.Error).message)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `teamDetails - response is RuntimeException - returns Resource Error`() = runTest {
|
||||||
|
// Arrange
|
||||||
|
coEvery { api.teamDetails("789") } throws RuntimeException("Unknown error")
|
||||||
|
|
||||||
|
// Act
|
||||||
|
val result = dataSource.teamDetails("789")
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertTrue(result is Resource.Error)
|
||||||
|
assertEquals("Unknown error", (result as Resource.Error).message)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val MATCH_DTO = MatchDto(
|
||||||
|
beginAt = null,
|
||||||
|
opponents = emptyList(),
|
||||||
|
league = LeagueDto(
|
||||||
|
id = 5078,
|
||||||
|
name = "United21",
|
||||||
|
imageUrl = "https://cdn.pandascore.co/images/league/image/5078/800px-united21_allmode-png"
|
||||||
|
),
|
||||||
|
serie = SerieDto(
|
||||||
|
id = 9519,
|
||||||
|
fullName = "Season 35 2025"
|
||||||
|
),
|
||||||
|
status = "not_started"
|
||||||
|
)
|
||||||
|
|
||||||
|
private val TEAM_DETAILS_DTO = TeamDetailsDto(
|
||||||
|
id = 123L,
|
||||||
|
name = "Team 1",
|
||||||
|
imageUrl = "",
|
||||||
|
players = emptyList()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,8 @@ kotlinxSerializationJson = "1.8.1"
|
||||||
okhttp = "4.12.0"
|
okhttp = "4.12.0"
|
||||||
coil = "3.2.0"
|
coil = "3.2.0"
|
||||||
hiltNavigation = "1.2.0"
|
hiltNavigation = "1.2.0"
|
||||||
|
mockk = "1.14.5"
|
||||||
|
coroutinesTest = "1.10.2"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
|
@ -45,6 +47,8 @@ kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-
|
||||||
okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
|
okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
|
||||||
coil-compose = { group = "io.coil-kt.coil3", name = "coil-compose", version.ref = "coil" }
|
coil-compose = { group = "io.coil-kt.coil3", name = "coil-compose", version.ref = "coil" }
|
||||||
coil-network = { group = "io.coil-kt.coil3", name = "coil-network-okhttp", version.ref = "coil" }
|
coil-network = { group = "io.coil-kt.coil3", name = "coil-network-okhttp", version.ref = "coil" }
|
||||||
|
mockk = { group = "io.mockk", name = "mockk", version.ref = "mockk" }
|
||||||
|
kotlinx-coroutines-test= { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "coroutinesTest" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
|
Loading…
Add table
Reference in a new issue