From f5067022bd2ce2c49911f524e27d50a7760be89d Mon Sep 17 00:00:00 2001 From: soopeach Date: Tue, 13 Dec 2022 10:55:05 +0900 Subject: [PATCH 1/5] =?UTF-8?q?:wrench:=20domain=20layer=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=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 --- domain/build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/domain/build.gradle b/domain/build.gradle index 0d2423bc..dbb30453 100644 --- a/domain/build.gradle +++ b/domain/build.gradle @@ -14,8 +14,13 @@ dependencies { // Coroutine implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxCoroutinesVersion" + // coroutineTest + testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinxCoroutinesVersion" // PagingData - Common implementation "androidx.paging:paging-common-ktx:$paging3Version" testImplementation "androidx.paging:paging-common:$paging3Version" + + // junit + testImplementation "junit:junit:$junitVersion" } \ No newline at end of file From 1571ec4121a2d9923acebfbc05a7273944325b88 Mon Sep 17 00:00:00 2001 From: soopeach Date: Tue, 13 Dec 2022 11:16:27 +0900 Subject: [PATCH 2/5] =?UTF-8?q?:white=5Fcheck=5Fmark:=20GetGroupInfoUseCas?= =?UTF-8?q?e=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80(=EC=9E=84=EC=8B=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../whyranoid/domain/model/FakeGroupInfo.kt | 24 ++++++ .../domain/repository/FakeGroupRepository.kt | 76 +++++++++++++++++++ .../domain/useCase/GetGroupInfoUseCaseTest.kt | 43 +++++++++++ 3 files changed, 143 insertions(+) create mode 100644 domain/src/test/java/com/whyranoid/domain/model/FakeGroupInfo.kt create mode 100644 domain/src/test/java/com/whyranoid/domain/repository/FakeGroupRepository.kt create mode 100644 domain/src/test/java/com/whyranoid/domain/useCase/GetGroupInfoUseCaseTest.kt diff --git a/domain/src/test/java/com/whyranoid/domain/model/FakeGroupInfo.kt b/domain/src/test/java/com/whyranoid/domain/model/FakeGroupInfo.kt new file mode 100644 index 00000000..ac8a2c6c --- /dev/null +++ b/domain/src/test/java/com/whyranoid/domain/model/FakeGroupInfo.kt @@ -0,0 +1,24 @@ +package com.whyranoid.domain.model + +class FakeGroupInfo private constructor() { + + companion object { + private var INSTANCE: GroupInfo? = null + + fun getInstance() = + INSTANCE ?: GroupInfo( + name = "fake", + groupId = "fake", + introduce = "fake", + rules = emptyList(), + headCount = 0, + leader = User( + uid = "fake", + name = "hyunsoo", + profileUrl = "fake" + ) + ).apply { + INSTANCE = this + } + } +} diff --git a/domain/src/test/java/com/whyranoid/domain/repository/FakeGroupRepository.kt b/domain/src/test/java/com/whyranoid/domain/repository/FakeGroupRepository.kt new file mode 100644 index 00000000..afe97de7 --- /dev/null +++ b/domain/src/test/java/com/whyranoid/domain/repository/FakeGroupRepository.kt @@ -0,0 +1,76 @@ +package com.whyranoid.domain.repository + +import com.whyranoid.domain.model.FakeGroupInfo +import com.whyranoid.domain.model.GroupInfo +import com.whyranoid.domain.model.GroupNotification +import com.whyranoid.domain.model.Rule +import com.whyranoid.domain.model.RunningHistory +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow + +val fakeGroupRepository = + object : GroupRepository { + + override fun getGroupInfoFlow(uid: String, groupId: String): Flow = + flow { + if (groupId == "fake") emit(FakeGroupInfo.getInstance()) + } + + override suspend fun getMyGroupList(uid: String): Result> { + TODO("Not yet implemented") + } + + override fun getMyGroupListFlow(uid: String): Flow> { + TODO("Not yet implemented") + } + + override suspend fun updateGroupInfo( + groupId: String, + groupName: String, + groupIntroduce: String, + rules: List + ): Boolean { + TODO("Not yet implemented") + } + + override suspend fun joinGroup(uid: String, groupId: String): Boolean { + TODO("Not yet implemented") + } + + override suspend fun exitGroup(uid: String, groupId: String): Boolean { + TODO("Not yet implemented") + } + + override fun getGroupNotifications(groupId: String): Flow> { + TODO("Not yet implemented") + } + + override suspend fun notifyRunningStart(uid: String, groupIdList: List) { + TODO("Not yet implemented") + } + + override suspend fun notifyRunningFinish( + uid: String, + runningHistory: RunningHistory, + groupIdList: List + ) { + TODO("Not yet implemented") + } + + override suspend fun createGroup( + groupName: String, + introduce: String, + rules: List, + uid: String + ): Boolean { + TODO("Not yet implemented") + } + + override suspend fun deleteGroup(uid: String, groupId: String): Boolean { + TODO("Not yet implemented") + } + + override suspend fun isDuplicatedGroupName(groupName: String): Boolean { + TODO("Not yet implemented") + } + } diff --git a/domain/src/test/java/com/whyranoid/domain/useCase/GetGroupInfoUseCaseTest.kt b/domain/src/test/java/com/whyranoid/domain/useCase/GetGroupInfoUseCaseTest.kt new file mode 100644 index 00000000..5d42a862 --- /dev/null +++ b/domain/src/test/java/com/whyranoid/domain/useCase/GetGroupInfoUseCaseTest.kt @@ -0,0 +1,43 @@ +package com.whyranoid.domain.useCase + +import com.whyranoid.domain.repository.fakeGroupRepository +import com.whyranoid.domain.usecase.GetGroupInfoUseCase +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.firstOrNull +import kotlinx.coroutines.test.runTest +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test + +class GetGroupInfoUseCaseTest { + + // uid는 상관없이 groupId가 "fake" 일 때 Leader의 name이 hyunsoo인 그룹을 flow로 반환 + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun getGroupInfoUseCase_groupIdIsFake_returnGroupInfo() = runTest { + // given + val getGroupInfoUseCase = + GetGroupInfoUseCase(fakeGroupRepository).invoke(uid = "fake", groupId = "fake") + + // when + val groupInfo = getGroupInfoUseCase.firstOrNull() + + // then + assertEquals("hyunsoo", (requireNotNull(groupInfo).leader.name)) + } + + // uid는 상관없이 groupId가 "fake" 가 아닐 때 그룹을 반환하지 않음 + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun getGroupInfoUseCase_groupIdIsNotFake_returnNothing() = runTest { + // given + val getGroupInfoUseCase = + GetGroupInfoUseCase(fakeGroupRepository).invoke(uid = "fake", groupId = "noFake") + + // when + val groupInfo = getGroupInfoUseCase.firstOrNull() + + // then + assertNull(groupInfo) + } +} From 2ed0ed90576a4d53c772364ce35511513450593f Mon Sep 17 00:00:00 2001 From: soopeach Date: Fri, 16 Dec 2022 01:11:59 +0900 Subject: [PATCH 3/5] =?UTF-8?q?:wrench:=20mockito=20=EA=B7=B8=EB=A0=88?= =?UTF-8?q?=EB=93=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 ++ domain/build.gradle | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/build.gradle b/build.gradle index da341988..a58466ee 100644 --- a/build.gradle +++ b/build.gradle @@ -36,6 +36,8 @@ buildscript { hiltCompilerVersion = "1.0.0" crashlyticsVersion = "2.9.2" swipeRefreshLayoutVersion = "1.1.0" + mockitoAndroidVersion = "2.24.5" + mockitoInlineVersion = "3.5.13" } dependencies { classpath "com.google.gms:google-services:$googleServiceVersion" diff --git a/domain/build.gradle b/domain/build.gradle index dbb30453..c4451704 100644 --- a/domain/build.gradle +++ b/domain/build.gradle @@ -23,4 +23,9 @@ dependencies { // junit testImplementation "junit:junit:$junitVersion" + + // mockito + testImplementation ("org.mockito:mockito-android:$mockitoAndroidVersion") + // mockito - kotlin + testImplementation "org.mockito:mockito-inline:$mockitoInlineVersion" } \ No newline at end of file From 117b49218faf798ad9d4259ae349293bbfbdd2ad Mon Sep 17 00:00:00 2001 From: soopeach Date: Fri, 16 Dec 2022 01:13:01 +0900 Subject: [PATCH 4/5] =?UTF-8?q?:wrench:=20mockito=20=EC=9D=B4=EC=8A=88=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0=EC=9D=84=20=EC=9C=84=ED=95=9C=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/mockito-extensions/org.mockito.plugins.MockMaker | 1 + 1 file changed, 1 insertion(+) create mode 100644 domain/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker diff --git a/domain/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/domain/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 00000000..ca6ee9ce --- /dev/null +++ b/domain/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline \ No newline at end of file From 3652ec7bf5d3382c44ec39d4adca8ea10eed555d Mon Sep 17 00:00:00 2001 From: soopeach Date: Fri, 16 Dec 2022 02:16:23 +0900 Subject: [PATCH 5/5] =?UTF-8?q?:white=5Fcheck=5Fmark:=20GetGroupInfoUseCas?= =?UTF-8?q?e=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20mockito?= =?UTF-8?q?=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../whyranoid/domain/model/FakeGroupInfo.kt | 24 ------ .../domain/repository/FakeGroupRepository.kt | 76 ------------------- .../domain/useCase/GetGroupInfoUseCaseTest.kt | 55 +++++++++++++- 3 files changed, 51 insertions(+), 104 deletions(-) delete mode 100644 domain/src/test/java/com/whyranoid/domain/model/FakeGroupInfo.kt delete mode 100644 domain/src/test/java/com/whyranoid/domain/repository/FakeGroupRepository.kt diff --git a/domain/src/test/java/com/whyranoid/domain/model/FakeGroupInfo.kt b/domain/src/test/java/com/whyranoid/domain/model/FakeGroupInfo.kt deleted file mode 100644 index ac8a2c6c..00000000 --- a/domain/src/test/java/com/whyranoid/domain/model/FakeGroupInfo.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.whyranoid.domain.model - -class FakeGroupInfo private constructor() { - - companion object { - private var INSTANCE: GroupInfo? = null - - fun getInstance() = - INSTANCE ?: GroupInfo( - name = "fake", - groupId = "fake", - introduce = "fake", - rules = emptyList(), - headCount = 0, - leader = User( - uid = "fake", - name = "hyunsoo", - profileUrl = "fake" - ) - ).apply { - INSTANCE = this - } - } -} diff --git a/domain/src/test/java/com/whyranoid/domain/repository/FakeGroupRepository.kt b/domain/src/test/java/com/whyranoid/domain/repository/FakeGroupRepository.kt deleted file mode 100644 index afe97de7..00000000 --- a/domain/src/test/java/com/whyranoid/domain/repository/FakeGroupRepository.kt +++ /dev/null @@ -1,76 +0,0 @@ -package com.whyranoid.domain.repository - -import com.whyranoid.domain.model.FakeGroupInfo -import com.whyranoid.domain.model.GroupInfo -import com.whyranoid.domain.model.GroupNotification -import com.whyranoid.domain.model.Rule -import com.whyranoid.domain.model.RunningHistory -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow - -val fakeGroupRepository = - object : GroupRepository { - - override fun getGroupInfoFlow(uid: String, groupId: String): Flow = - flow { - if (groupId == "fake") emit(FakeGroupInfo.getInstance()) - } - - override suspend fun getMyGroupList(uid: String): Result> { - TODO("Not yet implemented") - } - - override fun getMyGroupListFlow(uid: String): Flow> { - TODO("Not yet implemented") - } - - override suspend fun updateGroupInfo( - groupId: String, - groupName: String, - groupIntroduce: String, - rules: List - ): Boolean { - TODO("Not yet implemented") - } - - override suspend fun joinGroup(uid: String, groupId: String): Boolean { - TODO("Not yet implemented") - } - - override suspend fun exitGroup(uid: String, groupId: String): Boolean { - TODO("Not yet implemented") - } - - override fun getGroupNotifications(groupId: String): Flow> { - TODO("Not yet implemented") - } - - override suspend fun notifyRunningStart(uid: String, groupIdList: List) { - TODO("Not yet implemented") - } - - override suspend fun notifyRunningFinish( - uid: String, - runningHistory: RunningHistory, - groupIdList: List - ) { - TODO("Not yet implemented") - } - - override suspend fun createGroup( - groupName: String, - introduce: String, - rules: List, - uid: String - ): Boolean { - TODO("Not yet implemented") - } - - override suspend fun deleteGroup(uid: String, groupId: String): Boolean { - TODO("Not yet implemented") - } - - override suspend fun isDuplicatedGroupName(groupName: String): Boolean { - TODO("Not yet implemented") - } - } diff --git a/domain/src/test/java/com/whyranoid/domain/useCase/GetGroupInfoUseCaseTest.kt b/domain/src/test/java/com/whyranoid/domain/useCase/GetGroupInfoUseCaseTest.kt index 5d42a862..7d002730 100644 --- a/domain/src/test/java/com/whyranoid/domain/useCase/GetGroupInfoUseCaseTest.kt +++ b/domain/src/test/java/com/whyranoid/domain/useCase/GetGroupInfoUseCaseTest.kt @@ -1,29 +1,55 @@ package com.whyranoid.domain.useCase -import com.whyranoid.domain.repository.fakeGroupRepository +import com.whyranoid.domain.model.GroupInfo +import com.whyranoid.domain.model.User +import com.whyranoid.domain.repository.GroupRepository import com.whyranoid.domain.usecase.GetGroupInfoUseCase import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.firstOrNull +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.test.runTest import org.junit.Assert.assertEquals import org.junit.Assert.assertNull +import org.junit.Before import org.junit.Test +import org.mockito.Mockito.`when` +import org.mockito.Mockito.mock class GetGroupInfoUseCaseTest { + @Before + fun setUp() { + + mockedGroupRepository = mock(GroupRepository::class.java) + + `when`( + mockedGroupRepository.getGroupInfoFlow( + uid = FAKE, + groupId = IS_SUCCESS + ) + ).thenReturn(flow { emit(MOCKED_GROUP_INFO) }) + + `when`( + mockedGroupRepository.getGroupInfoFlow( + uid = FAKE, + groupId = IS_FAILURE + ) + ).thenReturn(flow { }) + } + // uid는 상관없이 groupId가 "fake" 일 때 Leader의 name이 hyunsoo인 그룹을 flow로 반환 @OptIn(ExperimentalCoroutinesApi::class) @Test fun getGroupInfoUseCase_groupIdIsFake_returnGroupInfo() = runTest { // given val getGroupInfoUseCase = - GetGroupInfoUseCase(fakeGroupRepository).invoke(uid = "fake", groupId = "fake") + GetGroupInfoUseCase(mockedGroupRepository).invoke(uid = FAKE, groupId = IS_SUCCESS) // when val groupInfo = getGroupInfoUseCase.firstOrNull() // then - assertEquals("hyunsoo", (requireNotNull(groupInfo).leader.name)) + assertEquals(IS_SUCCESS, (requireNotNull(groupInfo).leader.name)) } // uid는 상관없이 groupId가 "fake" 가 아닐 때 그룹을 반환하지 않음 @@ -32,7 +58,7 @@ class GetGroupInfoUseCaseTest { fun getGroupInfoUseCase_groupIdIsNotFake_returnNothing() = runTest { // given val getGroupInfoUseCase = - GetGroupInfoUseCase(fakeGroupRepository).invoke(uid = "fake", groupId = "noFake") + GetGroupInfoUseCase(mockedGroupRepository).invoke(uid = FAKE, groupId = IS_FAILURE) // when val groupInfo = getGroupInfoUseCase.firstOrNull() @@ -40,4 +66,25 @@ class GetGroupInfoUseCaseTest { // then assertNull(groupInfo) } + + companion object { + + private lateinit var mockedGroupRepository: GroupRepository + private const val FAKE = "fake" + private const val IS_SUCCESS = "isSuccess" + private const val IS_FAILURE = "isFailure" + + val MOCKED_GROUP_INFO = GroupInfo( + name = FAKE, + groupId = FAKE, + introduce = FAKE, + rules = emptyList(), + headCount = 0, + leader = User( + uid = FAKE, + name = IS_SUCCESS, + profileUrl = FAKE + ) + ) + } }