Skip to content

Commit

Permalink
Add Hilt-SavedState UI Test for AndroidTarget
Browse files Browse the repository at this point in the history
  • Loading branch information
easternkite committed Jan 21, 2025
1 parent 29d8140 commit 6175c09
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 3 deletions.
16 changes: 16 additions & 0 deletions androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.kotlinAndroid)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.hilt)
id("kotlin-kapt")
}

android {
Expand All @@ -13,6 +15,7 @@ android {
targetSdk = 35
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "com.easternkite.eungabi.android.HiltTestRunner"
}
buildFeatures {
compose = true
Expand Down Expand Up @@ -43,4 +46,17 @@ dependencies {
implementation(libs.compose.material3)
implementation(libs.androidx.activity.compose)
debugImplementation(libs.compose.ui.tooling)

implementation(libs.hilt.common)
kapt(libs.hilt.compiler)
implementation(libs.hilt.navigation)
implementation(libs.hilt.navigation.compose)

androidTestImplementation(libs.hilt.test.common)
kaptAndroidTest(libs.hilt.test.compiler)
testImplementation(libs.junit)

androidTestImplementation(libs.androidx.ui.test.junit4.android)
androidTestImplementation(libs.junit.ext)
androidTestImplementation(libs.androidx.test.runner)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package com.easternkite.eungabi.android

import androidx.activity.compose.setContent
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.test.assertTextEquals
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.easternkite.eungabi.navigation.EunGabiNavHost
import com.easternkite.eungabi.navigation.rememberEunGabiController
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import javax.inject.Inject

@RunWith(AndroidJUnit4::class)
@HiltAndroidTest
class EunGabiHiltTest {
@get:Rule
var hiltRule = HiltAndroidRule(this)

@get:Rule
var composeTestRule = createAndroidComposeRule<MainActivity>()

@Before
fun setUp() {
hiltRule.inject()
}

@Test
fun hiltNavigationTest() {
composeTestRule.activity.setContent {
HiltNavHost()
}

composeTestRule.apply {
waitForIdle()
onNodeWithTag("MainButton").performClick()
waitForIdle()
onNodeWithTag("state").assertTextEquals("SecondState")
}
}
}

@Composable
fun HiltNavHost(modifier: Modifier = Modifier) {
val controller = rememberEunGabiController()
EunGabiNavHost(
modifier = modifier,
controller = controller,
startDestination = "Main"
) {
composable("Main") {
Button(
onClick = { controller.navigate("Second?state=SecondState") },
modifier = Modifier.testTag("MainButton")
) {
Text("Main")
}
}
composable("Second") {
HiltView()
}
}
}

@Composable
fun HiltView(viewModel: HiltViewModel = hiltViewModel()) {
val state by viewModel.state.collectAsState()
Text(text = state, modifier = Modifier.testTag("state"))
}

@dagger.hilt.android.lifecycle.HiltViewModel
class HiltViewModel
@Inject
constructor(
savedStateHandle: SavedStateHandle
) : ViewModel() {
val state = savedStateHandle.getStateFlow("state", "state")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.easternkite.eungabi.android

import android.app.Application
import android.content.Context
import androidx.test.runner.AndroidJUnitRunner
import dagger.hilt.android.testing.HiltTestApplication

class HiltTestRunner : AndroidJUnitRunner() {
override fun newApplication(
cl: ClassLoader?,
className: String?,
context: Context?
): Application = super.newApplication(cl, HiltTestApplication::class.java.name, context)
}
1 change: 1 addition & 0 deletions androidApp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application
android:name=".android.Application"
android:allowBackup="false"
android:supportsRtl="true"
android:enableOnBackInvokedCallback="true"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.easternkite.eungabi.android

import android.app.Application
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class Application : Application()
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import com.easternkite.eungabi.SampleApp
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ plugins {
alias(libs.plugins.compose.multiplatform).apply(false)
alias(libs.plugins.nexus.publish).apply(false)
alias(libs.plugins.dokka).apply(false)
alias(libs.plugins.hilt).apply(false)
}
20 changes: 17 additions & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ compose = "1.7.6"
compose-material3 = "1.3.1"
cmp-plugin = "1.7.3"
androidx-activityCompose = "1.10.0"
lifecycleRuntimeKtx = "2.8.7"
jetbrains-lifecycle = "2.8.4"
nexus-publish = "0.30.0"
uiTestJunit4Android = "1.7.6"
Expand All @@ -15,21 +14,28 @@ napier = "2.7.1"
kotlinx-coroutines = "1.10.1"
dokka = "2.0.0"
kover = "0.9.1"
hilt-dagger = "2.51.1"
hilt-androidx = "1.2.0"
junit = "4.13.2"
junit-ext = "1.2.1"
runner = "1.6.2"

[libraries]
androidx-ui-test-junit4-android = { module = "androidx.compose.ui:ui-test-junit4-android", version.ref = "uiTestJunit4Android" }
androidx-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest", version.ref = "uiTestJunit4Android" }
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" }
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose" }
compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "compose" }
compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "compose" }
compose-foundation = { module = "androidx.compose.foundation:foundation", version.ref = "compose" }
compose-material3 = { module = "androidx.compose.material3:material3", version.ref = "compose-material3" }
kotlinx-coroutines-swing = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-swing", version.ref = "kotlinx-coroutines" }

junit = { module = "junit:junit", version.ref = "junit" }
junit-ext = {module = "androidx.test.ext:junit", version.ref = "junit-ext"}
androidx-test-runner = {module = "androidx.test:runner", version.ref = "runner"}

uri = { module = "com.eygraber:uri-kmp", version.ref = "uri-kmp" }
napier = { module = "io.github.aakira:napier", version.ref = "napier"}

Expand All @@ -38,6 +44,13 @@ jetbrains-lifecycle-viewModel = { group = "org.jetbrains.androidx.lifecycle", na
jetbrains-lifecycle-viewModel-compose = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "jetbrains-lifecycle" }
jetbrains-lifecycle-savedstate = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-viewmodel-savedstate", version.ref = "jetbrains-lifecycle" }

hilt-common = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt-dagger" }
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt-dagger" }
hilt-navigation = { group = "androidx.hilt", name = "hilt-navigation", version.ref = "hilt-androidx" }
hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hilt-androidx" }
hilt-test-common = { group = "com.google.dagger", "name" = "hilt-android-testing", version.ref = "hilt-dagger"}
hilt-test-compiler = { group = "com.google.dagger", "name" = "hilt-android-compiler", version.ref = "hilt-dagger"}

[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
androidLibrary = { id = "com.android.library", version.ref = "agp" }
Expand All @@ -48,3 +61,4 @@ compose-multiplatform = { id = "org.jetbrains.compose", version.ref = "cmp-plugi
nexus-publish = { id = "com.vanniktech.maven.publish", version.ref = "nexus-publish" }
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
kotlinxKover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" }
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt-dagger"}

0 comments on commit 6175c09

Please sign in to comment.