From 89bd57054fc2e42c8051c5c35d47021c6b24579c Mon Sep 17 00:00:00 2001 From: Wooyeol Lee Date: Fri, 8 Dec 2023 01:44:54 +0900 Subject: [PATCH 1/2] refactor: move sampleEmojiDto to utils.kt --- .../remote/EmojiRepositoryImplTest.kt | 12 +---------- .../test/java/com/goliath/emojihub/utils.kt | 20 +++++++++---------- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/android/app/src/test/java/com/goliath/emojihub/repositories/remote/EmojiRepositoryImplTest.kt b/android/app/src/test/java/com/goliath/emojihub/repositories/remote/EmojiRepositoryImplTest.kt index 731a233a..aac45f8c 100644 --- a/android/app/src/test/java/com/goliath/emojihub/repositories/remote/EmojiRepositoryImplTest.kt +++ b/android/app/src/test/java/com/goliath/emojihub/repositories/remote/EmojiRepositoryImplTest.kt @@ -5,8 +5,8 @@ import com.goliath.emojihub.data_sources.CustomError import com.goliath.emojihub.data_sources.api.EmojiApi import com.goliath.emojihub.data_sources.remote.EmojiDataSource import com.goliath.emojihub.mockLogClass -import com.goliath.emojihub.models.EmojiDto import com.goliath.emojihub.models.UploadEmojiDto +import com.goliath.emojihub.sampleEmojiDto import retrofit2.Response import io.mockk.coEvery import io.mockk.coVerify @@ -31,16 +31,6 @@ class EmojiRepositoryImplTest { private val emojiApi = mockk() private val emojiDataSource = mockk() private val emojiRepositoryImpl = EmojiRepositoryImpl(emojiApi, emojiDataSource) - private val sampleEmojiDto = EmojiDto( - createdBy = "channn", - createdAt = "2023-11-24 14:25:05", - savedCount = 1600, - videoLink = "https://storage.googleapis.com/emojihub-e2023.appspot.com/uu_2023-11-24%2014%3A25%3A05.mp4?GoogleAccessId=firebase-adminsdk-zynbm@emojihub-e2023.iam.gserviceaccount.com&Expires=1709443506&Signature=I%2BNRJSZ7nYtmrWs%2Fjv4uVAeW8%2BfHGF6GeV0pZRE4Sp5gCFuXLXBTKpgRBl1j2F%2BSSUStSqvBlktHZofZznGHWtsMYHQ99%2Bv7wcenqZweSWSmzse4s9sKAOkykn7pB9EMnFgax4VqGK4U5ey5HNSCKsjyNa5ZqDH8%2BqF%2FcIjQ3huChDMB2Xw1InaHUve0syvW6uz%2BeooDLo2nkGxdtElsDtomq2cAUMgk7nRNIYciYLGJ%2FsrscW7%2FXfD3rn%2BH3EM9z5S9DHKHWiEmh1xf0wpTtDsXom7p14XnZunnnOxpNO5OMFJi2x1kxZBFVc7U88V19eTmasWxdGV5TZipfN2ZMA%3D%3D", - thumbnailLink = "https://storage.googleapis.com/emojihub-e2023.appspot.com/uu_2023-11-24%2014%3A25%3A05.jpeg?GoogleAccessId=firebase-adminsdk-zynbm@emojihub-e2023.iam.gserviceaccount.com&Expires=1709443506&Signature=lZK4otdQOXBVKz3EeOEgpSqAH5QE3U6KuTz8bo5RwYQ463i0cBEx44zVPJO3dIP%2B3%2FdKkBbJy%2BzIBogKAKUl5jLyP9FwInOZChspQOuI8zp%2FKivvEZImPnoG2C1UiiwB03tHYq0tWEhgj76BB4SarWRtZY4xRZhuVvuJg9%2FNV%2B5XZ7%2BGGjLbzfjc5rA45iwWQGPfgQN0%2FKJsdTieNb5%2F6%2B5QHW4pq7QLxYAGqvea5X6VY1JcUjXU0iZ%2FfI16L%2F1cFZAMPDPNPxC2bbllFH6vkOdb3qKuvGm0M3Y99GCLTv%2BAiObbBCs13AgmBO1OngrBV4db4zNnjUZOtB0rPRgyFw%3D%3D", - id = "0ZF0MFHOV7974YTV3SBN", - label = "love it", - unicode = "U+2764 U+FE0F" - ) @Before fun setUp() { mockLogClass() diff --git a/android/app/src/test/java/com/goliath/emojihub/utils.kt b/android/app/src/test/java/com/goliath/emojihub/utils.kt index d579fa86..3e1f4334 100644 --- a/android/app/src/test/java/com/goliath/emojihub/utils.kt +++ b/android/app/src/test/java/com/goliath/emojihub/utils.kt @@ -24,17 +24,18 @@ fun mockLogClass() { every { Log.e(any(), any()) } returns 0 } -// USER TESTING UTILS -val sampleUserDetailsDto = UserDetailsDto( - email = "sampleEmail", - name = "sampleName", - password = "samplePassword", - savedEmojiList = listOf("a", "b", "c"), - createdEmojiList = listOf("d", "e", "f"), - createdPostList = listOf("g", "h", "i"), +// EMOJI TESTING UTILS +val sampleEmojiDto = EmojiDto( + createdBy = "channn", + createdAt = "2023-11-24 14:25:05", + savedCount = 1600, + videoLink = "https://storage.googleapis.com/emojihub-e2023.appspot.com/uu_2023-11-24%2014%3A25%3A05.mp4?GoogleAccessId=firebase-adminsdk-zynbm@emojihub-e2023.iam.gserviceaccount.com&Expires=1709443506&Signature=I%2BNRJSZ7nYtmrWs%2Fjv4uVAeW8%2BfHGF6GeV0pZRE4Sp5gCFuXLXBTKpgRBl1j2F%2BSSUStSqvBlktHZofZznGHWtsMYHQ99%2Bv7wcenqZweSWSmzse4s9sKAOkykn7pB9EMnFgax4VqGK4U5ey5HNSCKsjyNa5ZqDH8%2BqF%2FcIjQ3huChDMB2Xw1InaHUve0syvW6uz%2BeooDLo2nkGxdtElsDtomq2cAUMgk7nRNIYciYLGJ%2FsrscW7%2FXfD3rn%2BH3EM9z5S9DHKHWiEmh1xf0wpTtDsXom7p14XnZunnnOxpNO5OMFJi2x1kxZBFVc7U88V19eTmasWxdGV5TZipfN2ZMA%3D%3D", + thumbnailLink = "https://storage.googleapis.com/emojihub-e2023.appspot.com/uu_2023-11-24%2014%3A25%3A05.jpeg?GoogleAccessId=firebase-adminsdk-zynbm@emojihub-e2023.iam.gserviceaccount.com&Expires=1709443506&Signature=lZK4otdQOXBVKz3EeOEgpSqAH5QE3U6KuTz8bo5RwYQ463i0cBEx44zVPJO3dIP%2B3%2FdKkBbJy%2BzIBogKAKUl5jLyP9FwInOZChspQOuI8zp%2FKivvEZImPnoG2C1UiiwB03tHYq0tWEhgj76BB4SarWRtZY4xRZhuVvuJg9%2FNV%2B5XZ7%2BGGjLbzfjc5rA45iwWQGPfgQN0%2FKJsdTieNb5%2F6%2B5QHW4pq7QLxYAGqvea5X6VY1JcUjXU0iZ%2FfI16L%2F1cFZAMPDPNPxC2bbllFH6vkOdb3qKuvGm0M3Y99GCLTv%2BAiObbBCs13AgmBO1OngrBV4db4zNnjUZOtB0rPRgyFw%3D%3D", + id = "0ZF0MFHOV7974YTV3SBN", + label = "love it", + unicode = "U+2764 U+FE0F" ) -// EMOJI TESTING UTILS val dummyUsernames = listOf("channn", "doggydog", "meow_0w0", "mpunchmm", "kick_back") val dummyUnicodes = listOf("U+1F44D", "U+1F600", "U+1F970", "U+1F60E", "U+1F621", "U+1F63A", "U+1F496", "U+1F415") const val dummyMaxSavedCounts = 2000 @@ -100,7 +101,6 @@ fun createDeterministicDummyPostList(listSize: Int): Flow> { } // X3D TESTING UTILS - val sampleX3dInferenceResultListOverScoreThreshold = listOf( X3dInferenceResult(4, 0.8f), X3dInferenceResult(6, 0.15f), From 6ffd86eaac04dff17ae21db0ade5bf25906205db Mon Sep 17 00:00:00 2001 From: Wooyeol Lee Date: Fri, 8 Dec 2023 01:45:52 +0900 Subject: [PATCH 2/2] test: implement reaction unit test --- .../com/goliath/emojihub/models/Reaction.kt | 22 ++++ .../repositories/remote/ReactionRepository.kt | 6 +- .../emojihub/usecases/ReactionUseCase.kt | 10 +- .../emojihub/viewmodels/ReactionViewModel.kt | 2 +- .../remote/ReactionRepositoryImplTest.kt | 120 ++++++++++++++++++ .../usecases/ReactionUseCaseImplTest.kt | 103 +++++++++++++++ .../test/java/com/goliath/emojihub/utils.kt | 35 +++++ .../viewmodels/ReactionViewModelTest.kt | 94 ++++++++++++++ 8 files changed, 383 insertions(+), 9 deletions(-) create mode 100644 android/app/src/test/java/com/goliath/emojihub/repositories/remote/ReactionRepositoryImplTest.kt create mode 100644 android/app/src/test/java/com/goliath/emojihub/usecases/ReactionUseCaseImplTest.kt create mode 100644 android/app/src/test/java/com/goliath/emojihub/viewmodels/ReactionViewModelTest.kt diff --git a/android/app/src/main/java/com/goliath/emojihub/models/Reaction.kt b/android/app/src/main/java/com/goliath/emojihub/models/Reaction.kt index 109e0c08..c5b2439a 100644 --- a/android/app/src/main/java/com/goliath/emojihub/models/Reaction.kt +++ b/android/app/src/main/java/com/goliath/emojihub/models/Reaction.kt @@ -47,4 +47,26 @@ class ReactionWithEmoji( val emojiId: String = dto.emojiId val postId: String = dto.postId val emojiDto: EmojiDto? = dto.emojiDto + + override fun equals(other: Any?): Boolean { + if (other == null || other !is ReactionWithEmoji) { + return false + } + return this.id == other.id && + this.createdAt == other.createdAt && + this.createdBy == other.createdBy && + this.emojiId == other.emojiId && + this.postId == other.postId && + this.emojiDto == other.emojiDto + } + + override fun hashCode(): Int { + var result = id.hashCode() + result = 31 * result + createdAt.hashCode() + result = 31 * result + createdBy.hashCode() + result = 31 * result + emojiId.hashCode() + result = 31 * result + postId.hashCode() + result = 31 * result + (emojiDto?.hashCode() ?: 0) + return result + } } diff --git a/android/app/src/main/java/com/goliath/emojihub/repositories/remote/ReactionRepository.kt b/android/app/src/main/java/com/goliath/emojihub/repositories/remote/ReactionRepository.kt index 9e8ba76c..8dc3e78a 100644 --- a/android/app/src/main/java/com/goliath/emojihub/repositories/remote/ReactionRepository.kt +++ b/android/app/src/main/java/com/goliath/emojihub/repositories/remote/ReactionRepository.kt @@ -15,7 +15,7 @@ interface ReactionRepository { suspend fun fetchReactionList(postId: String, emojiUnicode: String): Flow> suspend fun uploadReaction(postId: String, emojiId: String): Response suspend fun getReactionWithId(id: String) - suspend fun deleteReaction(reactionId: String) + suspend fun deleteReaction(reactionId: String): Response } @Singleton @@ -37,7 +37,7 @@ class ReactionRepositoryImpl @Inject constructor( TODO() } - override suspend fun deleteReaction(reactionId: String) { - reactionApi.deleteReaction(reactionId) + override suspend fun deleteReaction(reactionId: String): Response { + return reactionApi.deleteReaction(reactionId) } } \ No newline at end of file diff --git a/android/app/src/main/java/com/goliath/emojihub/usecases/ReactionUseCase.kt b/android/app/src/main/java/com/goliath/emojihub/usecases/ReactionUseCase.kt index 6ed5d23c..3b204029 100644 --- a/android/app/src/main/java/com/goliath/emojihub/usecases/ReactionUseCase.kt +++ b/android/app/src/main/java/com/goliath/emojihub/usecases/ReactionUseCase.kt @@ -24,7 +24,7 @@ interface ReactionUseCase { @Singleton class ReactionUseCaseImpl @Inject constructor( - private val repository: ReactionRepository, + private val reactionRepository: ReactionRepository, private val errorController: ApiErrorController ): ReactionUseCase { @@ -37,11 +37,11 @@ class ReactionUseCaseImpl @Inject constructor( } override suspend fun fetchReactionList(postId: String, emojiUnicode: String): Flow> { - return repository.fetchReactionList(postId, emojiUnicode).map { it.map { dto -> ReactionWithEmoji(dto) } } + return reactionRepository.fetchReactionList(postId, emojiUnicode).map { it.map { dto -> ReactionWithEmoji(dto) } } } override suspend fun uploadReaction(postId: String, emojiId: String): Boolean { - val response = repository.uploadReaction(postId, emojiId) + val response = reactionRepository.uploadReaction(postId, emojiId) return if (response.isSuccessful) { true } else { @@ -51,10 +51,10 @@ class ReactionUseCaseImpl @Inject constructor( } override suspend fun getReactionWithId(id: String) { - repository.getReactionWithId(id) + reactionRepository.getReactionWithId(id) } override suspend fun deleteReaction(reactionId: String) { - repository.deleteReaction(reactionId) + reactionRepository.deleteReaction(reactionId) } } \ No newline at end of file diff --git a/android/app/src/main/java/com/goliath/emojihub/viewmodels/ReactionViewModel.kt b/android/app/src/main/java/com/goliath/emojihub/viewmodels/ReactionViewModel.kt index ab5d67f1..7f1588db 100644 --- a/android/app/src/main/java/com/goliath/emojihub/viewmodels/ReactionViewModel.kt +++ b/android/app/src/main/java/com/goliath/emojihub/viewmodels/ReactionViewModel.kt @@ -15,7 +15,7 @@ class ReactionViewModel @Inject constructor( val reactionList = reactionUseCase.reactionList - suspend fun fetchReactionList(postId: String, emojiUnicode: String) { + fun fetchReactionList(postId: String, emojiUnicode: String) { viewModelScope.launch { reactionUseCase.fetchReactionList(postId, emojiUnicode) .cachedIn(viewModelScope) diff --git a/android/app/src/test/java/com/goliath/emojihub/repositories/remote/ReactionRepositoryImplTest.kt b/android/app/src/test/java/com/goliath/emojihub/repositories/remote/ReactionRepositoryImplTest.kt new file mode 100644 index 00000000..2a395236 --- /dev/null +++ b/android/app/src/test/java/com/goliath/emojihub/repositories/remote/ReactionRepositoryImplTest.kt @@ -0,0 +1,120 @@ +package com.goliath.emojihub.repositories.remote + +import androidx.paging.testing.asSnapshot +import com.goliath.emojihub.data_sources.api.ReactionApi +import com.goliath.emojihub.mockLogClass +import com.goliath.emojihub.sampleReactionWithEmojiDto +import io.mockk.coEvery +import io.mockk.coVerify +import io.mockk.mockk +import kotlinx.coroutines.runBlocking +import org.junit.Assert.* +import org.junit.Before + +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import retrofit2.Response + +@RunWith(JUnit4::class) +class ReactionRepositoryImplTest { + private val reactionApi = mockk() + private val reactionRepository = ReactionRepositoryImpl(reactionApi) + @Before + fun setUp() { + mockLogClass() + } + + @Test + fun fetchReactionList_returnsFlowOfPagingDataOfReactionWithEmojiDto() { + val numSampleReactions = 10 + val sampleReactionWithEmojiDtoList = List(numSampleReactions) { sampleReactionWithEmojiDto } + val expectedFetchedReactionWithEmojiDtoList = List(numSampleReactions*2) { sampleReactionWithEmojiDto } + // *2 because of .asSnapshot() load one more time + coEvery { + reactionApi.fetchReactionList(any(), any(), any(), any()) + } returns Response.success(sampleReactionWithEmojiDtoList) + // when + val fetchedReactionPagingDataFlow = runBlocking { + reactionRepository.fetchReactionList("1234", "U+1F44D") + } + val fetchedReactionWithEmojiDtoList = runBlocking { + fetchedReactionPagingDataFlow.asSnapshot() + } + // then + coVerify(exactly = 2) { reactionApi.fetchReactionList(any(), any(), any(), any()) } + runBlocking { + assertEquals(expectedFetchedReactionWithEmojiDtoList.size, fetchedReactionWithEmojiDtoList.size) + assertEquals(expectedFetchedReactionWithEmojiDtoList, fetchedReactionWithEmojiDtoList) + } + } + + @Test + fun uploadReaction_success_returnsSuccessResponse() { + // given + val expectedResponse = Response.success(Unit) + coEvery { + reactionApi.uploadReaction(any(), any()) + } returns expectedResponse + // when + val response = runBlocking { + reactionRepository.uploadReaction("1234", "1234") + } + // then + coVerify(exactly = 1) { reactionApi.uploadReaction(any(), any()) } + assertEquals(expectedResponse, response) + } + + @Test + fun uploadReaction_failure_returnsFailureResponse() { + // given + val expectedResponse = Response.error(400, mockk(relaxed = true)) + coEvery { + reactionApi.uploadReaction(any(), any()) + } returns expectedResponse + // when + val response = runBlocking { + reactionRepository.uploadReaction("1234", "1234") + } + // then + coVerify(exactly = 1) { reactionApi.uploadReaction(any(), any()) } + assertFalse(response.isSuccessful) + } + + // @Test + // TODO: Not implemented yet + fun getReactionWithId() { + } + + @Test + fun deleteReaction_success_returnsSuccessResponse() { + // given + val expectedResponse = Response.success(Unit) + coEvery { + reactionApi.deleteReaction(any()) + } returns expectedResponse + // when + val response = runBlocking { + reactionRepository.deleteReaction("1234") + } + // then + coVerify(exactly = 1) { reactionApi.deleteReaction(any()) } + assertEquals(expectedResponse, response) + } + + @Test + fun deleteReaction_failure_returnsFailureResponse() { + // given + val expectedResponse = Response.error(400, mockk(relaxed = true)) + coEvery { + reactionApi.deleteReaction(any()) + } returns expectedResponse + // when + val response = runBlocking { + reactionRepository.deleteReaction("1234") + } + // then + coVerify(exactly = 1) { reactionApi.deleteReaction(any()) } + assertFalse(response.isSuccessful) + } +} \ No newline at end of file diff --git a/android/app/src/test/java/com/goliath/emojihub/usecases/ReactionUseCaseImplTest.kt b/android/app/src/test/java/com/goliath/emojihub/usecases/ReactionUseCaseImplTest.kt new file mode 100644 index 00000000..d5ac0ba6 --- /dev/null +++ b/android/app/src/test/java/com/goliath/emojihub/usecases/ReactionUseCaseImplTest.kt @@ -0,0 +1,103 @@ +package com.goliath.emojihub.usecases + +import androidx.paging.PagingData +import androidx.paging.map +import androidx.paging.testing.asSnapshot +import com.goliath.emojihub.createReactionWithEmojiDtoList +import com.goliath.emojihub.data_sources.ApiErrorController +import com.goliath.emojihub.mockLogClass +import com.goliath.emojihub.models.ReactionWithEmoji +import com.goliath.emojihub.repositories.remote.ReactionRepository +import io.mockk.coEvery +import io.mockk.coVerify +import io.mockk.mockk +import io.mockk.spyk +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.runBlocking +import org.junit.Assert.* +import org.junit.Before + +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import retrofit2.Response + +@RunWith(JUnit4::class) +class ReactionUseCaseImplTest { + private val reactionRepository = mockk() + private val apiErrorController = spyk() + private val reactionUseCase = ReactionUseCaseImpl(reactionRepository, apiErrorController) + @Before + fun setUp() { + mockLogClass() + } + + @Test + fun updateReactionList_withSamplePagingReactionData_updatesReactionListStateFlow() { + // given + val samplePagingReactionData = mockk>() + // when + runBlocking { reactionUseCase.updateReactionList(samplePagingReactionData) } + // then + assertEquals(samplePagingReactionData, reactionUseCase.reactionList.value) + } + + @Test + fun fetchReactionList_returnsFlowOfReactionPagingData() { + // given + val sampleReactionPagingDataFlow = createReactionWithEmojiDtoList(5) + val sampleAnswer = sampleReactionPagingDataFlow.map { it.map { dto -> ReactionWithEmoji(dto) } } + coEvery { + reactionRepository.fetchReactionList(any(), any()) + } returns sampleReactionPagingDataFlow + // when + val result = runBlocking { reactionUseCase.fetchReactionList("1234", "U+1F44D") } + // then + coVerify(exactly = 1) { reactionRepository.fetchReactionList(any(), any()) } + runBlocking { + val sampleAnswerAsSnapshot = sampleAnswer.asSnapshot() + val resultAsSnapshot = result.asSnapshot() + for (i in sampleAnswerAsSnapshot.indices) { + assertEquals(sampleAnswerAsSnapshot[i], resultAsSnapshot[i]) + } + } + } + + @Test + fun uploadReaction_successWithValidPostId_returnsTrue() { + // given + val samplePostId = "1234" + val sampleEmojiId = "5678" + coEvery { + reactionRepository.uploadReaction(any(), any()) + } returns Response.success(Unit) + // when + val result = runBlocking { reactionUseCase.uploadReaction(samplePostId, sampleEmojiId) } + // then + assertTrue(result) + } + + @Test + fun uploadReaction_failureWithInvalidPostId_returnsFalse() { + // given + val samplePostId = "-1234" + val sampleEmojiId = "5678" + coEvery { + reactionRepository.uploadReaction(any(), any()) + } returns Response.error(404, mockk(relaxed = true)) + // when + val result = runBlocking { reactionUseCase.uploadReaction(samplePostId, sampleEmojiId) } + // then + assertFalse(result) + } + + // @Test + // TODO: Not implemented yet + fun getReactionWithId() { + } + + // @Test + // TODO: Not implemented yet + fun deleteReaction() { + } +} \ No newline at end of file diff --git a/android/app/src/test/java/com/goliath/emojihub/utils.kt b/android/app/src/test/java/com/goliath/emojihub/utils.kt index 3e1f4334..ef11ab00 100644 --- a/android/app/src/test/java/com/goliath/emojihub/utils.kt +++ b/android/app/src/test/java/com/goliath/emojihub/utils.kt @@ -7,6 +7,8 @@ import com.goliath.emojihub.models.Emoji import com.goliath.emojihub.models.EmojiDto import com.goliath.emojihub.models.Post import com.goliath.emojihub.models.PostDto +import com.goliath.emojihub.models.ReactionWithEmoji +import com.goliath.emojihub.models.ReactionWithEmojiDto import com.goliath.emojihub.models.ReactionWithEmojiUnicode import com.goliath.emojihub.models.UserDetailsDto import com.goliath.emojihub.models.X3dInferenceResult @@ -100,6 +102,39 @@ fun createDeterministicDummyPostList(listSize: Int): Flow> { return createDeterministicDummyPostDtoList(listSize).map { it.map { dto -> Post(dto) } } } +// REACTION TESTING UTILS +val sampleReactionWithEmojiDto = ReactionWithEmojiDto( + id = "1234", + createdAt = "2023.09.16", + createdBy = "channn", + emojiId = "3456", + postId = "5678", + emojiDto = sampleEmojiDto +) + +fun createReactionWithEmojiDtoList(listSize : Int): Flow> { + val dummyReactionList = mutableListOf() + for (i in 0 until listSize) { + dummyReactionList.add(sampleReactionWithEmojiDto) + } + return flowOf(PagingData.from(dummyReactionList)) +} + +fun createReactionWithEmojiList(listSize: Int): Flow> { + return createReactionWithEmojiDtoList(listSize).map { it.map { dto -> ReactionWithEmoji(dto) } } +} + + +// USER TESTING UTILS +val sampleUserDetailsDto = UserDetailsDto( + email = "sampleEmail", + name = "sampleName", + password = "samplePassword", + savedEmojiList = listOf("a", "b", "c"), + createdEmojiList = listOf("d", "e", "f"), + createdPostList = listOf("g", "h", "i"), +) + // X3D TESTING UTILS val sampleX3dInferenceResultListOverScoreThreshold = listOf( X3dInferenceResult(4, 0.8f), diff --git a/android/app/src/test/java/com/goliath/emojihub/viewmodels/ReactionViewModelTest.kt b/android/app/src/test/java/com/goliath/emojihub/viewmodels/ReactionViewModelTest.kt new file mode 100644 index 00000000..045eeba6 --- /dev/null +++ b/android/app/src/test/java/com/goliath/emojihub/viewmodels/ReactionViewModelTest.kt @@ -0,0 +1,94 @@ +package com.goliath.emojihub.viewmodels + +import com.goliath.emojihub.createReactionWithEmojiList +import com.goliath.emojihub.mockLogClass +import com.goliath.emojihub.usecases.ReactionUseCase +import io.mockk.coEvery +import io.mockk.coVerify +import io.mockk.spyk +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.advanceUntilIdle +import kotlinx.coroutines.test.resetMain +import kotlinx.coroutines.test.runTest +import kotlinx.coroutines.test.setMain +import org.junit.After +import org.junit.Assert.* +import org.junit.Before + +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@RunWith(JUnit4::class) +@OptIn(ExperimentalCoroutinesApi::class) +class ReactionViewModelTest { + private val reactionUseCase = spyk() + private val reactionViewModel = ReactionViewModel(reactionUseCase) + + private val testDispatcher = StandardTestDispatcher() + @Before + fun setUp() { + Dispatchers.setMain(testDispatcher) + mockLogClass() + } + @After + fun cleanUp() { + Dispatchers.resetMain() + } + + @Test + fun fetchReactionList_success_updateReactionList() = runTest { + // given + val sampleFetchedReactionList = createReactionWithEmojiList(5) + coEvery { + reactionUseCase.fetchReactionList(any(), any()) + } returns sampleFetchedReactionList + // when + reactionViewModel.fetchReactionList("1234", "U+1F44D") + advanceUntilIdle() + // then + coVerify(exactly = 1) { reactionUseCase.fetchReactionList(any(), any()) } + coVerify(exactly = 1) { reactionUseCase.updateReactionList(any()) } + } + + @Test + fun uploadReaction_success_returnsTrue() { + // given + coEvery { + reactionUseCase.uploadReaction(any(), any()) + } returns true + // when + val result = runBlocking { + reactionViewModel.uploadReaction("1234", "1234") + } + // then + assertTrue(result) + } + + @Test + fun uploadReaction_failure_returnsFalse() { + // given + coEvery { + reactionUseCase.uploadReaction(any(), any()) + } returns false + // when + val result = runBlocking { + reactionViewModel.uploadReaction("1234", "1234") + } + // then + assertFalse(result) + } + + // @Test + // TODO: Not implemented yet + fun getReactionWithId() { + } + + // @Test + // TODO: Not implemented yet + fun deleteReaction() { + } +} \ No newline at end of file