From 52180e82a72667711c12c85d744b9fd2d5fa6b0c Mon Sep 17 00:00:00 2001 From: Hyunwoo Choi Date: Sun, 17 Apr 2022 21:17:56 +0900 Subject: [PATCH 1/9] =?UTF-8?q?Local=20test=20:=20StatisticsUtilsTest=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../todoapp/statistics/StatisticsUtilsTest.kt | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 app/src/test/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtilsTest.kt diff --git a/app/src/test/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtilsTest.kt b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtilsTest.kt new file mode 100644 index 0000000..dc50e58 --- /dev/null +++ b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtilsTest.kt @@ -0,0 +1,28 @@ +package com.example.android.architecture.blueprints.todoapp.statistics + +import com.example.android.architecture.blueprints.todoapp.data.Task +import org.junit.Assert.* +import org.junit.Test + +class StatisticsUtilsTest { + + // 1. 앞서 생성한 테스트 클래스를 open + // 2. 테스트 함수를 생성. + // 3. 테스트임을 나타내기 위해 함수 이름 위에 @Test annotation을 추가. + @Test + fun getActiveAndCompletedStats_완료된작업이없는경우엔_zero로계산되는가() { + + // 4. 작업 목록 만들기 + val tasks = listOf( + Task("title", "desc", isCompleted = false) + ) + // 5. 계산 함수인 getActiveAndCompletedStats()를 호출 + val result = getActiveAndCompletedStats(tasks) + + // 6. assertion을 사용하여 결과를 확인 + assertEquals(result.completedTasksPercent, 0f) + assertEquals(result.activeTasksPercent, 100f) + } + + +} \ No newline at end of file From 868295970dc00fd19d69ff9b9daefa21cfe7bd91 Mon Sep 17 00:00:00 2001 From: Hyunwoo Choi Date: Mon, 18 Apr 2022 11:15:32 +0900 Subject: [PATCH 2/9] =?UTF-8?q?Local=20test=20:=20Hamcrest=20=EC=A2=85?= =?UTF-8?q?=EC=86=8D=EC=84=B1=20=EC=B6=94=EA=B0=80=20/=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 3 +++ .../blueprints/todoapp/statistics/StatisticsUtilsTest.kt | 7 ++++--- build.gradle | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index edea693..8edb4ad 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -60,4 +60,7 @@ dependencies { // Kotlin implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" implementation "androidx.fragment:fragment-ktx:$fragmentKtxVersion" + + // Other dependencies + testImplementation "org.hamcrest:hamcrest-all:$hamcrestVersion" } diff --git a/app/src/test/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtilsTest.kt b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtilsTest.kt index dc50e58..e29c827 100644 --- a/app/src/test/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtilsTest.kt +++ b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtilsTest.kt @@ -1,7 +1,8 @@ package com.example.android.architecture.blueprints.todoapp.statistics import com.example.android.architecture.blueprints.todoapp.data.Task -import org.junit.Assert.* +import org.hamcrest.CoreMatchers.`is` +import org.hamcrest.MatcherAssert.assertThat import org.junit.Test class StatisticsUtilsTest { @@ -20,8 +21,8 @@ class StatisticsUtilsTest { val result = getActiveAndCompletedStats(tasks) // 6. assertion을 사용하여 결과를 확인 - assertEquals(result.completedTasksPercent, 0f) - assertEquals(result.activeTasksPercent, 100f) + assertThat(result.completedTasksPercent, `is`(0f)) + assertThat(result.activeTasksPercent, `is`(100f)) } diff --git a/build.gradle b/build.gradle index c851a43..982ebb8 100644 --- a/build.gradle +++ b/build.gradle @@ -48,4 +48,5 @@ ext { rulesVersion = '1.0.1' swipeRefreshLayoutVersion = '1.1.0' timberVersion = '4.7.1' + hamcrestVersion = '1.3' } From 1911c8c4d33e87e750e7b3e09137face1532bf0b Mon Sep 17 00:00:00 2001 From: Hyunwoo Choi Date: Mon, 18 Apr 2022 20:14:52 +0900 Subject: [PATCH 3/9] =?UTF-8?q?TDD=20(1)=20:=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=EC=9D=84=20=EC=9C=84=ED=95=9C=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../todoapp/statistics/StatisticsUtilsTest.kt | 52 ++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/app/src/test/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtilsTest.kt b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtilsTest.kt index e29c827..2668893 100644 --- a/app/src/test/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtilsTest.kt +++ b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtilsTest.kt @@ -11,7 +11,7 @@ class StatisticsUtilsTest { // 2. 테스트 함수를 생성. // 3. 테스트임을 나타내기 위해 함수 이름 위에 @Test annotation을 추가. @Test - fun getActiveAndCompletedStats_완료된작업이없는경우엔_zero로계산되는가() { + fun getActiveAndCompletedStats_완료된작업이없으면_100과_0으로_계산되는가() { // 4. 작업 목록 만들기 val tasks = listOf( @@ -25,5 +25,55 @@ class StatisticsUtilsTest { assertThat(result.activeTasksPercent, `is`(100f)) } + @Test + fun getActiveAndCompletedStats_활성화된작업이없으면_0과_100으로_계산되는가() { + val tasks = listOf( + Task("title", "desc", isCompleted = true) + ) + // When the list of tasks is computed with a completed task + val result = getActiveAndCompletedStats(tasks) + + // Then the percentages are 0 and 100 + assertThat(result.activeTasksPercent, `is`(0f)) + assertThat(result.completedTasksPercent, `is`(100f)) + } + + @Test + fun getActiveAndCompletedStats_active와complete두경우모두_제대로계산되는가() { + // Given 3 completed tasks and 2 active tasks + val tasks = listOf( + Task("title", "desc", isCompleted = true), + Task("title", "desc", isCompleted = true), + Task("title", "desc", isCompleted = true), + Task("title", "desc", isCompleted = false), + Task("title", "desc", isCompleted = false) + ) + // When the list of tasks is computed + val result = getActiveAndCompletedStats(tasks) + + // Then the result is 40-60 + assertThat(result.activeTasksPercent, `is`(40f)) + assertThat(result.completedTasksPercent, `is`(60f)) + } + + @Test + fun getActiveAndCompletedStats_null이입력되면_0을리턴하는가() { + // When there's an error loading stats + val result = getActiveAndCompletedStats(null) + + // Both active and completed tasks are 0 + assertThat(result.activeTasksPercent, `is`(0f)) + assertThat(result.completedTasksPercent, `is`(0f)) + } + + @Test + fun getActiveAndCompletedStats_빈리스트가입력되면_0을리턴하는가() { + // When there are no tasks + val result = getActiveAndCompletedStats(emptyList()) + + // Both active and completed tasks are 0 + assertThat(result.activeTasksPercent, `is`(0f)) + assertThat(result.completedTasksPercent, `is`(0f)) + } } \ No newline at end of file From 41eb9ab7e9c47449037e18f9d7768e0cb9d0e874 Mon Sep 17 00:00:00 2001 From: Hyunwoo Choi Date: Mon, 18 Apr 2022 20:19:10 +0900 Subject: [PATCH 4/9] =?UTF-8?q?TDD=20(2)=20:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=8B=A4=ED=8C=A8=20=ED=99=95=EC=9D=B8=20=ED=9B=84=20getAct?= =?UTF-8?q?iveAndCompletedStats()=20=ED=95=A8=EC=88=98=EC=9D=98=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit null 또는 empty list 에 대한 처리 추가. --- .../todoapp/statistics/StatisticsUtils.kt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtils.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtils.kt index 968b8f1..7ffd78d 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtils.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/statistics/StatisticsUtils.kt @@ -22,12 +22,16 @@ import com.example.android.architecture.blueprints.todoapp.data.Task * Function that does some trivial computation. Used to showcase unit tests. */ internal fun getActiveAndCompletedStats(tasks: List?): StatsResult { - val totalTasks = tasks!!.size - val numberOfActiveTasks = tasks.count { it.isActive } - return StatsResult( - activeTasksPercent = 100f * numberOfActiveTasks / tasks.size, - completedTasksPercent = 100f * (totalTasks - numberOfActiveTasks) / tasks.size - ) + return if (tasks == null || tasks.isEmpty()) { + StatsResult(0f, 0f) + } else { + val totalTasks = tasks.size + val numberOfActiveTasks = tasks.count { it.isActive } + StatsResult( + activeTasksPercent = 100f * numberOfActiveTasks / tasks.size, + completedTasksPercent = 100f * (totalTasks - numberOfActiveTasks) / tasks.size + ) + } } data class StatsResult(val activeTasksPercent: Float, val completedTasksPercent: Float) From 50fdf4710530553e5731bbf9f8f2ee7d941e455a Mon Sep 17 00:00:00 2001 From: Hyunwoo Choi Date: Mon, 18 Apr 2022 22:00:54 +0900 Subject: [PATCH 5/9] =?UTF-8?q?AndroidXTest=20(1)=20:=20=20ViewModel=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EB=A5=BC=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AndroidX 테스트 라이브러리 & 로블렉트릭 의존성 추가 androidx.test.ext:junit-ktx androidx.test:core-ktx org.robolectric:robolectric --- app/build.gradle | 6 ++++++ build.gradle | 1 + 2 files changed, 7 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index 8edb4ad..77b85ad 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -63,4 +63,10 @@ dependencies { // Other dependencies testImplementation "org.hamcrest:hamcrest-all:$hamcrestVersion" + + // AndroidX Test - JVM testing + testImplementation "androidx.test.ext:junit-ktx:$androidXTestExtKotlinRunnerVersion" + testImplementation "androidx.test:core-ktx:$androidXTestCoreVersion" + testImplementation "org.robolectric:robolectric:$robolectricVersion" + } diff --git a/build.gradle b/build.gradle index 982ebb8..980a973 100644 --- a/build.gradle +++ b/build.gradle @@ -49,4 +49,5 @@ ext { swipeRefreshLayoutVersion = '1.1.0' timberVersion = '4.7.1' hamcrestVersion = '1.3' + robolectricVersion = '4.4' } From 2e8eaff00280078148f9b76d0f92514cbf5351df Mon Sep 17 00:00:00 2001 From: Hyunwoo Choi Date: Mon, 18 Apr 2022 22:01:24 +0900 Subject: [PATCH 6/9] =?UTF-8?q?AndroidXTest=20(2)=20:=20=EB=B7=B0=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 뷰모델의 LiveData에 할당된 Event가 잘 동작하는지 테스트. --- .../todoapp/tasks/TasksViewModel.kt | 1 + .../todoapp/tasks/TasksViewModelTest.kt | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 app/src/test/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModelTest.kt diff --git a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModel.kt b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModel.kt index 8cc67bb..e600c12 100644 --- a/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModel.kt +++ b/app/src/main/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModel.kt @@ -160,6 +160,7 @@ class TasksViewModel(application: Application) : AndroidViewModel(application) { /** * Called by the Data Binding library and the FAB's click listener. */ + // local test 수행할 함수 fun addNewTask() { _newTaskEvent.value = Event(Unit) } diff --git a/app/src/test/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModelTest.kt b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModelTest.kt new file mode 100644 index 0000000..51b87fe --- /dev/null +++ b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModelTest.kt @@ -0,0 +1,29 @@ +package com.example.android.architecture.blueprints.todoapp.tasks + +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Assert.* + +import org.junit.Test +import org.junit.runner.RunWith + +// AndroidX Test 라이브러리의 annotation +@RunWith(AndroidJUnit4::class) +class TasksViewModelTest { + + @Test + fun addNewTask() { + + // Given a fresh ViewModel + // AndroidX Test 라이브러리로부터 applicationContext를 얻어와 뷰모델을 생성한다. + val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext()) + + // When adding a new task + tasksViewModel.addNewTask() + + // Then the new task event is triggered + // TODO test LiveData + + } + +} \ No newline at end of file From 44b2bc905ea4588bb2e6cc135c96100ee35b9dd1 Mon Sep 17 00:00:00 2001 From: Hyunwoo Choi Date: Tue, 19 Apr 2022 03:31:01 +0900 Subject: [PATCH 7/9] =?UTF-8?q?LiveDataTestAssertion=20(1)=20:=20=EC=95=84?= =?UTF-8?q?=ED=82=A4=ED=85=8D=EC=B2=98=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8C=85=20=EB=9D=BC=EC=9D=B4=EB=B8=8C?= =?UTF-8?q?=EB=9F=AC=EB=A6=AC=20=EC=A2=85=EC=86=8D=EC=84=B1=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 3 +++ build.gradle | 1 + 2 files changed, 4 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index 77b85ad..580ca6b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -69,4 +69,7 @@ dependencies { testImplementation "androidx.test:core-ktx:$androidXTestCoreVersion" testImplementation "org.robolectric:robolectric:$robolectricVersion" + // Architecture Components core testing library (for LiveData test) + testImplementation "androidx.arch.core:core-testing:$archTestingVersion" + } diff --git a/build.gradle b/build.gradle index 980a973..7495e05 100644 --- a/build.gradle +++ b/build.gradle @@ -50,4 +50,5 @@ ext { timberVersion = '4.7.1' hamcrestVersion = '1.3' robolectricVersion = '4.4' + archTestingVersion = '2.1.0' } From 5e956035d8eaf2a072528ad05cf2ae5b207fa69c Mon Sep 17 00:00:00 2001 From: Hyunwoo Choi Date: Tue, 19 Apr 2022 03:35:50 +0900 Subject: [PATCH 8/9] =?UTF-8?q?LiveDataTestAssertion=20(2)=20:=20LiveData?= =?UTF-8?q?=20assertion=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (1) InstantTaskExecutorRule : JUnit 테스트 룰. 테스트에 사용되는 아키텍처 컴포넌트의 백그라운드 작업이 단일 스레드에서 동작하도록 함. (2) observeForever() : LiveData 구독 시 동작하므로, 강제로 임의의 observer를 구독하도록 함. 테스트 종료 전 구독 해제 필수. --- .../todoapp/tasks/TasksViewModelTest.kt | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/app/src/test/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModelTest.kt b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModelTest.kt index 51b87fe..273daf1 100644 --- a/app/src/test/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModelTest.kt +++ b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModelTest.kt @@ -1,8 +1,14 @@ package com.example.android.architecture.blueprints.todoapp.tasks +import androidx.arch.core.executor.testing.InstantTaskExecutorRule +import androidx.lifecycle.Observer import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 -import org.junit.Assert.* +import com.example.android.architecture.blueprints.todoapp.Event +import org.hamcrest.CoreMatchers.not +import org.hamcrest.CoreMatchers.nullValue +import org.hamcrest.MatcherAssert.assertThat +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -11,18 +17,33 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class TasksViewModelTest { + @get:Rule + var instantExecutorRule = InstantTaskExecutorRule() + @Test - fun addNewTask() { + fun addNewTask_setsNewTaskEvent() { // Given a fresh ViewModel - // AndroidX Test 라이브러리로부터 applicationContext를 얻어와 뷰모델을 생성한다. val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext()) - // When adding a new task - tasksViewModel.addNewTask() + // Create observer - no need for it to do anything! + val observer = Observer> {} + try { + + // Observe the LiveData forever + tasksViewModel.newTaskEvent.observeForever(observer) + + // When adding a new task + tasksViewModel.addNewTask() + + // Then the new task event is triggered + val value = tasksViewModel.newTaskEvent.value + assertThat(value?.getContentIfNotHandled(), (not(nullValue()))) - // Then the new task event is triggered - // TODO test LiveData + } finally { + // Whatever happens, don't forget to remove the observer! + tasksViewModel.newTaskEvent.removeObserver(observer) + } } From 8ac2766a2f8ba2f05be4744359afb4bc99f75180 Mon Sep 17 00:00:00 2001 From: Hyunwoo Choi Date: Tue, 19 Apr 2022 03:37:46 +0900 Subject: [PATCH 9/9] =?UTF-8?q?LiveDataTestAssertion=20(3)=20:=20observeFo?= =?UTF-8?q?rever=20=EA=B4=80=EB=A6=AC=ED=95=98=EB=8A=94=20boilerplate=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LiveData의 observeForever 주기 관리하는 로직을 Kotlin 확장함수로 선언하여 개선 --- .../blueprints/todoapp/LiveDataTestUtil.kt | 45 +++++++++++++++++++ .../todoapp/tasks/TasksViewModelTest.kt | 25 ++++------- 2 files changed, 53 insertions(+), 17 deletions(-) create mode 100644 app/src/test/java/com/example/android/architecture/blueprints/todoapp/LiveDataTestUtil.kt diff --git a/app/src/test/java/com/example/android/architecture/blueprints/todoapp/LiveDataTestUtil.kt b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/LiveDataTestUtil.kt new file mode 100644 index 0000000..e3eaa18 --- /dev/null +++ b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/LiveDataTestUtil.kt @@ -0,0 +1,45 @@ +package com.example.android.architecture.blueprints.todoapp + +import androidx.annotation.VisibleForTesting +import androidx.lifecycle.LiveData +import androidx.lifecycle.Observer +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit +import java.util.concurrent.TimeoutException + + +/** + * observeForever()로 등록된 옵저버를 해제하도록 작성된 확장 함수. + */ +@VisibleForTesting(otherwise = VisibleForTesting.NONE) +fun LiveData.getOrAwaitValue( + time: Long = 2, + timeUnit: TimeUnit = TimeUnit.SECONDS, + afterObserve: () -> Unit = {} +): T { + var data: T? = null + val latch = CountDownLatch(1) + val observer = object : Observer { + override fun onChanged(o: T?) { + data = o + latch.countDown() + this@getOrAwaitValue.removeObserver(this) + } + } + this.observeForever(observer) + + try { + afterObserve.invoke() + + // Don't wait indefinitely if the LiveData is not set. + if (!latch.await(time, timeUnit)) { + throw TimeoutException("LiveData value was never set.") + } + + } finally { + this.removeObserver(observer) + } + + @Suppress("UNCHECKED_CAST") + return data as T +} \ No newline at end of file diff --git a/app/src/test/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModelTest.kt b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModelTest.kt index 273daf1..22226db 100644 --- a/app/src/test/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModelTest.kt +++ b/app/src/test/java/com/example/android/architecture/blueprints/todoapp/tasks/TasksViewModelTest.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.Observer import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.example.android.architecture.blueprints.todoapp.Event +import com.example.android.architecture.blueprints.todoapp.getOrAwaitValue import org.hamcrest.CoreMatchers.not import org.hamcrest.CoreMatchers.nullValue import org.hamcrest.MatcherAssert.assertThat @@ -24,27 +25,17 @@ class TasksViewModelTest { fun addNewTask_setsNewTaskEvent() { // Given a fresh ViewModel + // AndroidX Test 라이브러리로부터 applicationContext를 얻어와 뷰모델을 생성한다. val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext()) - // Create observer - no need for it to do anything! - val observer = Observer> {} - try { + // When adding a new task + tasksViewModel.addNewTask() - // Observe the LiveData forever - tasksViewModel.newTaskEvent.observeForever(observer) - - // When adding a new task - tasksViewModel.addNewTask() - - // Then the new task event is triggered - val value = tasksViewModel.newTaskEvent.value - assertThat(value?.getContentIfNotHandled(), (not(nullValue()))) - - } finally { - // Whatever happens, don't forget to remove the observer! - tasksViewModel.newTaskEvent.removeObserver(observer) - } + // Then the new task event is triggered + val value = tasksViewModel.newTaskEvent.getOrAwaitValue() + // LiveData 캐싱 이슈 방지를 위한 getContentIfNotHandled() 호출 참고. + assertThat(value.getContentIfNotHandled(), (not(nullValue()))) } } \ No newline at end of file