Skip to content

Commit

Permalink
Merge pull request #28 from adidas/feature/add-tests-to-sample
Browse files Browse the repository at this point in the history
Added tests to sample
  • Loading branch information
jzeferino authored Apr 29, 2024
2 parents d852719 + a1840fa commit 9d7a7e5
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 5 deletions.
11 changes: 7 additions & 4 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ ktlint-gradle = "12.1.0"
android-library = "8.3.1"
maven-publish = "0.25.2"
ui = "1.6.5"

mockk = "1.13.10"
mvi-kotest = "0.0.2"
# its beeing used outside this file
ktlint-lib = "1.2.1"

Expand All @@ -26,9 +27,10 @@ appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat"
coroutinesCore = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
coroutinesTest = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" }
kotestRunner = { module = "io.kotest:kotest-runner-junit5", version.ref = "kotest" }
kotlinBom = { group = "org.jetbrains.kotlin", name = "kotlin-bom", version.ref = "kotlin" }
mvi = { group = "com.adidas.mvi", name = "mvi", version.ref = "mvi" }
mviCompose = { group = "com.adidas.mvi", name = "mvi-compose", version.ref = "mvi-compose" }
kotlinBom = { module = "org.jetbrains.kotlin:kotlin-bom", version.ref = "kotlin" }
mvi = { module = "com.adidas.mvi:mvi", version.ref = "mvi" }
mviCompose = { module = "com.adidas.mvi:mvi-compose", version.ref = "mvi-compose" }
mviKotest = { module = "com.adidas.mvi:mvi-kotest", version.ref = "mvi-kotest" }
activityCompose = { module = "androidx.activity:activity-compose", version.ref = "activity" }
lifecycleRuntimeCompose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycle" }
material = { module = "androidx.compose.material:material", version.ref = "material" }
Expand All @@ -38,6 +40,7 @@ koinAndroid = { module = "io.insert-koin:koin-android", version.ref = "koin-andr
koinAnnotations = { module = "io.insert-koin:koin-annotations", version.ref = "koin-annotations" }
koinKspCompiler = { module = "io.insert-koin:koin-ksp-compiler", version.ref = "koin-annotations" }
koinCompose = { module = "io.insert-koin:koin-androidx-compose", version.ref = "koin-compose" }
mockk = { module = "io.mockk:mockk", version.ref = "mockk" }

[plugins]
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
Expand Down
10 changes: 10 additions & 0 deletions mvi-sample/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ android {
applyKSP(this@configure, applicationVariants)
}
}

android.testOptions {
unitTests.all {
it.useJUnitPlatform()
}
}
}

private fun <T : BaseVariant> applyKSP(
Expand Down Expand Up @@ -83,4 +89,8 @@ dependencies {
implementation(libs.koinAnnotations)
implementation(libs.koinCompose)
ksp(libs.koinKspCompiler)

testImplementation(libs.kotestRunner)
testImplementation(libs.mockk)
testImplementation(libs.mviKotest)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.adidas.mvi.State
import com.adidas.mvi.reducer.Reducer
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.flow

internal class LoginViewModel(
Expand Down Expand Up @@ -48,7 +49,7 @@ internal class LoginViewModel(
private fun executeLogin(intent: LoginIntent.Login) = flow {
emit(LoginTransform.SetIsLoggingIn(isLoggingIn = true))

kotlinx.coroutines.delay(300)
delay(300)

emit(LoginTransform.SetIsLoggingIn(isLoggingIn = false))

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.adidas.mvi.sample.login.viewmodel

import io.kotest.core.listeners.TestListener
import io.kotest.core.test.TestCase
import io.kotest.core.test.TestResult
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.cancel
import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain

@OptIn(ExperimentalCoroutinesApi::class)
internal class CoroutineListener(
private val testCoroutineDispatcher: TestDispatcher,
) : TestListener {

override suspend fun beforeContainer(testCase: TestCase) {
Dispatchers.setMain(testCoroutineDispatcher)
}

override suspend fun afterContainer(testCase: TestCase, result: TestResult) {
Dispatchers.resetMain()
testCoroutineDispatcher.scheduler.cancel()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.adidas.mvi.sample.login.viewmodel

import com.adidas.mvi.kotest.GivenViewModel
import io.kotest.core.spec.IsolationMode
import io.kotest.core.spec.style.BehaviorSpec
import io.kotest.matchers.shouldBe
import io.mockk.mockk
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineScheduler
import kotlinx.coroutines.test.UnconfinedTestDispatcher

@OptIn(ExperimentalCoroutinesApi::class)
class LoginViewModelTest : BehaviorSpec({

isolationMode = IsolationMode.InstancePerLeaf

val testCoroutineDispatcher = UnconfinedTestDispatcher(TestCoroutineScheduler())
listeners(CoroutineListener(testCoroutineDispatcher))

fun getViewModel(): LoginViewModel {
return LoginViewModel(
logger = mockk(relaxed = true),
coroutineDispatcher = testCoroutineDispatcher
)
}

GivenViewModel(::getViewModel) {
When("no intent is executed") {
ThenState<LoginState.LoggedOut>()
}

WhenIntent(LoginIntent.Close) {
ThenState<LoginState.LoggedOut>(LoginSideEffect.Close)
}

WhenIntent(LoginIntent.Login("username", "password")) {

ThenState<LoginState.LoggedOut> { state ->
state.view.isLoggingIn shouldBe true
}

testCoroutineDispatcher.scheduler.advanceUntilIdle()

ThenState<LoginState.LoggedIn>()
}

WhenIntent(LoginIntent.Logout) {
ThenState<LoginState.LoggedOut>()
}

WhenIntent(LoginIntent.Login("", "")) {
testCoroutineDispatcher.scheduler.advanceUntilIdle()

ThenState<LoginState.LoggedOut>(LoginSideEffect.ShowInvalidCredentialsError)
}

}

})

0 comments on commit 9d7a7e5

Please sign in to comment.