From 3ce1db12b477c43bcfa1a344191c291fb9a534fd Mon Sep 17 00:00:00 2001 From: MyungHyun Ryu Date: Fri, 3 Nov 2023 12:42:58 +0900 Subject: [PATCH 1/3] :sparkles: Implement test --- frontend/app/build.gradle.kts | 5 + .../speechbuddy/service/AuthServiceTest.kt | 217 ++++++++++++++++++ 2 files changed, 222 insertions(+) create mode 100644 frontend/app/src/test/java/com/example/speechbuddy/service/AuthServiceTest.kt diff --git a/frontend/app/build.gradle.kts b/frontend/app/build.gradle.kts index 2968081b..c0e18af0 100644 --- a/frontend/app/build.gradle.kts +++ b/frontend/app/build.gradle.kts @@ -68,6 +68,8 @@ dependencies { debugImplementation("androidx.compose.ui:ui-tooling") debugImplementation("androidx.compose.ui:ui-test-manifest") + testImplementation("io.mockk:mockk:1.13.8") + // Lifecycle val lifecycleVersion = "2.6.2" implementation("androidx.lifecycle:lifecycle-common:$lifecycleVersion") @@ -82,6 +84,9 @@ dependencies { val coroutinesVersion = "1.7.1" implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion") + + // Coroutines test + testImplementation ("org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion") // Preference implementation("androidx.preference:preference-ktx:1.2.1") diff --git a/frontend/app/src/test/java/com/example/speechbuddy/service/AuthServiceTest.kt b/frontend/app/src/test/java/com/example/speechbuddy/service/AuthServiceTest.kt new file mode 100644 index 00000000..9b324164 --- /dev/null +++ b/frontend/app/src/test/java/com/example/speechbuddy/service/AuthServiceTest.kt @@ -0,0 +1,217 @@ +package com.example.speechbuddy.service + +import com.example.speechbuddy.data.remote.models.AuthTokenDto +import com.example.speechbuddy.data.remote.requests.AuthLoginRequest +import com.example.speechbuddy.data.remote.requests.AuthResetPasswordRequest +import com.example.speechbuddy.data.remote.requests.AuthSignupRequest +import com.example.speechbuddy.data.remote.requests.AuthVerifyEmailAcceptRequest +import com.example.speechbuddy.data.remote.requests.AuthVerifyEmailSendRequest +import io.mockk.coEvery +import io.mockk.coVerify +import io.mockk.mockk +import kotlinx.coroutines.runBlocking +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.ResponseBody.Companion.toResponseBody +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import retrofit2.Response + +class AuthServiceTest { + private lateinit var authService: AuthService + private val mockEmail = "test@example.com" + private val mockPassword = "password123" + private val mockNickname = "TestUser" + private val mockCode = "123456" + private val errorResponseBody = + "{\"error\":\"Something went wrong\"}".toResponseBody("application/json".toMediaType()) + + @Before + fun setUp() { + authService = mockk() + } + + @Test + fun signup_AuthSignupRequest_returnResponseSuccess() = runBlocking { + val signupRequest = AuthSignupRequest(mockEmail, mockPassword, mockNickname) + coEvery { authService.signup(signupRequest) } returns Response.success(null) + + val response = authService.signup(signupRequest) + + coVerify(exactly = 1) { authService.signup(signupRequest) } + assertTrue(response.isSuccessful) + } + + @Test + fun login_AuthLoginRequest_returnResponseSuccess() = runBlocking { + val loginRequest = AuthLoginRequest(mockEmail, mockPassword) + val authTokenDto = AuthTokenDto("AccessToken", "RefreshToken") + coEvery { authService.login(loginRequest) } returns Response.success(authTokenDto) + + val response = authService.login(loginRequest) + + coVerify(exactly = 1) { authService.login(loginRequest) } + assertTrue(response.isSuccessful) + assertTrue(response.body()?.accessToken == "AccessToken") + assertTrue(response.body()?.refreshToken == "RefreshToken") + } + + @Test + fun verifySendSignup_AuthVerifyEmailSendRequest_returnResponseSuccess() = runBlocking { + val verifyEmailSendRequest = AuthVerifyEmailSendRequest(mockEmail) + coEvery { authService.verifySendSignup(verifyEmailSendRequest) } returns Response.success( + null + ) + + val response = authService.verifySendSignup(verifyEmailSendRequest) + + coVerify(exactly = 1) { authService.verifySendSignup(verifyEmailSendRequest) } + assertTrue(response.isSuccessful) + } + + @Test + fun verifySendPW_AuthVerifyEmailSendRequest_returnResponseSuccess() = runBlocking { + val verifyEmailSendRequest = AuthVerifyEmailSendRequest(mockEmail) + coEvery { authService.verifySendPW(verifyEmailSendRequest) } returns Response.success(null) + + val response = authService.verifySendPW(verifyEmailSendRequest) + + coVerify(exactly = 1) { authService.verifySendPW(verifyEmailSendRequest) } + assertTrue(response.isSuccessful) + } + + @Test + fun verifyAcceptSignup_AuthVerifyEmailAcceptRequest_returnResponseSuccess() = runBlocking { + val verifyEmailAcceptRequest = AuthVerifyEmailAcceptRequest(mockEmail, mockCode) + coEvery { authService.verifyAcceptSignup(verifyEmailAcceptRequest) } returns Response.success( + null + ) + + val response = authService.verifyAcceptSignup(verifyEmailAcceptRequest) + + coVerify(exactly = 1) { authService.verifyAcceptSignup(verifyEmailAcceptRequest) } + assertTrue(response.isSuccessful) + } + + @Test + fun verifyAcceptPW_AuthVerifyEmailAccpetRequest_returnResponseSuccess() = runBlocking { + val verifyEmailAcceptRequest = AuthVerifyEmailAcceptRequest(mockEmail, mockCode) + val authTokenDto = AuthTokenDto("AccessToken", "RefreshToken") + coEvery { authService.verifyAcceptPW(verifyEmailAcceptRequest) } returns Response.success( + authTokenDto + ) + + val response = authService.verifyAcceptPW(verifyEmailAcceptRequest) + + coVerify(exactly = 1) { authService.verifyAcceptPW(verifyEmailAcceptRequest) } + assertTrue(response.isSuccessful) + assertTrue(response.body()?.accessToken == "AccessToken") + assertTrue(response.body()?.refreshToken == "RefreshToken") + } + + @Test + fun resetPassword_AuthResetPasswordRequest_returnResponseSuccess() = runBlocking { + val resetPasswordRequest = AuthResetPasswordRequest(mockPassword) + coEvery { authService.resetPassword(resetPasswordRequest) } returns Response.success(null) + + val response = authService.resetPassword(resetPasswordRequest) + + coVerify(exactly = 1) { authService.resetPassword(resetPasswordRequest) } + assertTrue(response.isSuccessful) + } + + + // Test Error Case + @Test + fun signup_AuthSignupRequest_returnResponseFail() = runBlocking { + val signupRequest = AuthSignupRequest(mockEmail, "short", mockNickname) + coEvery { authService.signup(signupRequest) } returns Response.error(400, errorResponseBody) + + val response = authService.signup(signupRequest) + + coVerify(exactly = 1) { authService.signup(signupRequest) } + assertFalse(response.isSuccessful) + } + + @Test + fun login_AuthLoginRequest_returnResponseFail() = runBlocking { + val loginRequest = AuthLoginRequest(mockEmail, "wrongpassword") + coEvery { authService.login(loginRequest) } returns Response.error(401, errorResponseBody) + + val response = authService.login(loginRequest) + + coVerify(exactly = 1) { authService.login(loginRequest) } + assertFalse(response.isSuccessful) + } + + @Test + fun verifySendSignup_AuthVerifyEmailSendRequest_returnResponseFail() = runBlocking { + val verifyEmailSendRequest = AuthVerifyEmailSendRequest("invalid_email") + coEvery { authService.verifySendSignup(verifyEmailSendRequest) } returns Response.error( + 400, + errorResponseBody + ) + + val response = authService.verifySendSignup(verifyEmailSendRequest) + + coVerify(exactly = 1) { authService.verifySendSignup(verifyEmailSendRequest) } + assertFalse(response.isSuccessful) + } + + @Test + fun verifySendPW_AuthVerifyEmailSendRequest_returnResponseFail() = runBlocking { + val verifyEmailSendRequest = AuthVerifyEmailSendRequest("invalid_email") + coEvery { authService.verifySendPW(verifyEmailSendRequest) } returns Response.error( + 400, + errorResponseBody + ) + + val response = authService.verifySendPW(verifyEmailSendRequest) + + coVerify(exactly = 1) { authService.verifySendPW(verifyEmailSendRequest) } + assertFalse(response.isSuccessful) + } + + @Test + fun verifyAcceptSignup_AuthVerifyEmailAcceptRequest_returnResponseFail() = runBlocking { + val verifyEmailAcceptRequest = AuthVerifyEmailAcceptRequest(mockEmail, "wrongcode") + coEvery { authService.verifyAcceptSignup(verifyEmailAcceptRequest) } returns Response.error( + 400, + errorResponseBody + ) + + val response = authService.verifyAcceptSignup(verifyEmailAcceptRequest) + + coVerify(exactly = 1) { authService.verifyAcceptSignup(verifyEmailAcceptRequest) } + assertFalse(response.isSuccessful) + } + + @Test + fun verifyAcceptPW_AuthVerifyEmailAcceptRequest_returnResponseFail() = runBlocking { + val verifyEmailAcceptRequest = AuthVerifyEmailAcceptRequest(mockEmail, "wrongcode") + coEvery { authService.verifyAcceptPW(verifyEmailAcceptRequest) } returns Response.error( + 400, + errorResponseBody + ) + + val response = authService.verifyAcceptPW(verifyEmailAcceptRequest) + + coVerify(exactly = 1) { authService.verifyAcceptPW(verifyEmailAcceptRequest) } + assertFalse(response.isSuccessful) + } + + @Test + fun resetPassword_AuthResetPasswordRequest_returnResponseFail() = runBlocking { + val resetPasswordRequest = AuthResetPasswordRequest("short") + coEvery { authService.resetPassword(resetPasswordRequest) } returns Response.error( + 400, + errorResponseBody + ) + + val response = authService.resetPassword(resetPasswordRequest) + + coVerify(exactly = 1) { authService.resetPassword(resetPasswordRequest) } + assertFalse(response.isSuccessful) + } +} From 2d60aed15edab1e764e6d3a4cbbb61d6761d0b28 Mon Sep 17 00:00:00 2001 From: MyungHyun Ryu Date: Fri, 3 Nov 2023 15:34:13 +0900 Subject: [PATCH 2/3] :white_check_mark: Change function name --- .../speechbuddy/service/AuthServiceTest.kt | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/frontend/app/src/test/java/com/example/speechbuddy/service/AuthServiceTest.kt b/frontend/app/src/test/java/com/example/speechbuddy/service/AuthServiceTest.kt index 9b324164..1bce94bd 100644 --- a/frontend/app/src/test/java/com/example/speechbuddy/service/AuthServiceTest.kt +++ b/frontend/app/src/test/java/com/example/speechbuddy/service/AuthServiceTest.kt @@ -33,7 +33,7 @@ class AuthServiceTest { } @Test - fun signup_AuthSignupRequest_returnResponseSuccess() = runBlocking { + fun `should return response success when signup request is valid`() = runBlocking { val signupRequest = AuthSignupRequest(mockEmail, mockPassword, mockNickname) coEvery { authService.signup(signupRequest) } returns Response.success(null) @@ -44,7 +44,7 @@ class AuthServiceTest { } @Test - fun login_AuthLoginRequest_returnResponseSuccess() = runBlocking { + fun `should return response with auth token dto when login request is valid`() = runBlocking { val loginRequest = AuthLoginRequest(mockEmail, mockPassword) val authTokenDto = AuthTokenDto("AccessToken", "RefreshToken") coEvery { authService.login(loginRequest) } returns Response.success(authTokenDto) @@ -58,7 +58,7 @@ class AuthServiceTest { } @Test - fun verifySendSignup_AuthVerifyEmailSendRequest_returnResponseSuccess() = runBlocking { + fun `should return response success when request email send is valid for signup`() = runBlocking { val verifyEmailSendRequest = AuthVerifyEmailSendRequest(mockEmail) coEvery { authService.verifySendSignup(verifyEmailSendRequest) } returns Response.success( null @@ -71,7 +71,7 @@ class AuthServiceTest { } @Test - fun verifySendPW_AuthVerifyEmailSendRequest_returnResponseSuccess() = runBlocking { + fun `should return response success when request email send is valid for password reset`() = runBlocking { val verifyEmailSendRequest = AuthVerifyEmailSendRequest(mockEmail) coEvery { authService.verifySendPW(verifyEmailSendRequest) } returns Response.success(null) @@ -82,7 +82,7 @@ class AuthServiceTest { } @Test - fun verifyAcceptSignup_AuthVerifyEmailAcceptRequest_returnResponseSuccess() = runBlocking { + fun `should return response with success when request code is valid for signup`() = runBlocking { val verifyEmailAcceptRequest = AuthVerifyEmailAcceptRequest(mockEmail, mockCode) coEvery { authService.verifyAcceptSignup(verifyEmailAcceptRequest) } returns Response.success( null @@ -95,7 +95,7 @@ class AuthServiceTest { } @Test - fun verifyAcceptPW_AuthVerifyEmailAccpetRequest_returnResponseSuccess() = runBlocking { + fun `should return response with auth token dto when request code is valid for password reset`() = runBlocking { val verifyEmailAcceptRequest = AuthVerifyEmailAcceptRequest(mockEmail, mockCode) val authTokenDto = AuthTokenDto("AccessToken", "RefreshToken") coEvery { authService.verifyAcceptPW(verifyEmailAcceptRequest) } returns Response.success( @@ -111,7 +111,7 @@ class AuthServiceTest { } @Test - fun resetPassword_AuthResetPasswordRequest_returnResponseSuccess() = runBlocking { + fun `should return response with success when request is valid password`() = runBlocking { val resetPasswordRequest = AuthResetPasswordRequest(mockPassword) coEvery { authService.resetPassword(resetPasswordRequest) } returns Response.success(null) @@ -124,7 +124,7 @@ class AuthServiceTest { // Test Error Case @Test - fun signup_AuthSignupRequest_returnResponseFail() = runBlocking { + fun `should return response with error when signup request is invalid`() = runBlocking { val signupRequest = AuthSignupRequest(mockEmail, "short", mockNickname) coEvery { authService.signup(signupRequest) } returns Response.error(400, errorResponseBody) @@ -135,7 +135,7 @@ class AuthServiceTest { } @Test - fun login_AuthLoginRequest_returnResponseFail() = runBlocking { + fun `should return response with error when login request is invalid`() = runBlocking { val loginRequest = AuthLoginRequest(mockEmail, "wrongpassword") coEvery { authService.login(loginRequest) } returns Response.error(401, errorResponseBody) @@ -146,7 +146,7 @@ class AuthServiceTest { } @Test - fun verifySendSignup_AuthVerifyEmailSendRequest_returnResponseFail() = runBlocking { + fun `should return response with error when reques temail send is invalid for signup`() = runBlocking { val verifyEmailSendRequest = AuthVerifyEmailSendRequest("invalid_email") coEvery { authService.verifySendSignup(verifyEmailSendRequest) } returns Response.error( 400, @@ -160,7 +160,7 @@ class AuthServiceTest { } @Test - fun verifySendPW_AuthVerifyEmailSendRequest_returnResponseFail() = runBlocking { + fun `should return response with error when request email send is invalid for password reset`() = runBlocking { val verifyEmailSendRequest = AuthVerifyEmailSendRequest("invalid_email") coEvery { authService.verifySendPW(verifyEmailSendRequest) } returns Response.error( 400, @@ -174,7 +174,7 @@ class AuthServiceTest { } @Test - fun verifyAcceptSignup_AuthVerifyEmailAcceptRequest_returnResponseFail() = runBlocking { + fun `should return response with error when request code is invalid for signup`() = runBlocking { val verifyEmailAcceptRequest = AuthVerifyEmailAcceptRequest(mockEmail, "wrongcode") coEvery { authService.verifyAcceptSignup(verifyEmailAcceptRequest) } returns Response.error( 400, @@ -188,7 +188,7 @@ class AuthServiceTest { } @Test - fun verifyAcceptPW_AuthVerifyEmailAcceptRequest_returnResponseFail() = runBlocking { + fun `should return response with error when request code is invalid for password reset`() = runBlocking { val verifyEmailAcceptRequest = AuthVerifyEmailAcceptRequest(mockEmail, "wrongcode") coEvery { authService.verifyAcceptPW(verifyEmailAcceptRequest) } returns Response.error( 400, @@ -202,7 +202,7 @@ class AuthServiceTest { } @Test - fun resetPassword_AuthResetPasswordRequest_returnResponseFail() = runBlocking { + fun `should return response with error when request is invalid password`() = runBlocking { val resetPasswordRequest = AuthResetPasswordRequest("short") coEvery { authService.resetPassword(resetPasswordRequest) } returns Response.error( 400, From ba323d3ad0a1ac4efb821c2871c04cd042844a20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=A5=98=EB=AA=85=ED=98=84?= Date: Fri, 3 Nov 2023 21:26:25 +0900 Subject: [PATCH 3/3] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 이석찬 / Lee Sukchan --- .../example/speechbuddy/service/AuthServiceTest.kt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/frontend/app/src/test/java/com/example/speechbuddy/service/AuthServiceTest.kt b/frontend/app/src/test/java/com/example/speechbuddy/service/AuthServiceTest.kt index 1bce94bd..9c4f2002 100644 --- a/frontend/app/src/test/java/com/example/speechbuddy/service/AuthServiceTest.kt +++ b/frontend/app/src/test/java/com/example/speechbuddy/service/AuthServiceTest.kt @@ -19,11 +19,14 @@ import org.junit.Test import retrofit2.Response class AuthServiceTest { + private lateinit var authService: AuthService + private val mockEmail = "test@example.com" private val mockPassword = "password123" private val mockNickname = "TestUser" private val mockCode = "123456" + private val errorResponseBody = "{\"error\":\"Something went wrong\"}".toResponseBody("application/json".toMediaType()) @@ -136,7 +139,7 @@ class AuthServiceTest { @Test fun `should return response with error when login request is invalid`() = runBlocking { - val loginRequest = AuthLoginRequest(mockEmail, "wrongpassword") + val loginRequest = AuthLoginRequest(mockEmail, "wrong_password") coEvery { authService.login(loginRequest) } returns Response.error(401, errorResponseBody) val response = authService.login(loginRequest) @@ -146,7 +149,7 @@ class AuthServiceTest { } @Test - fun `should return response with error when reques temail send is invalid for signup`() = runBlocking { + fun `should return response with error when request email send is invalid for signup`() = runBlocking { val verifyEmailSendRequest = AuthVerifyEmailSendRequest("invalid_email") coEvery { authService.verifySendSignup(verifyEmailSendRequest) } returns Response.error( 400, @@ -175,7 +178,7 @@ class AuthServiceTest { @Test fun `should return response with error when request code is invalid for signup`() = runBlocking { - val verifyEmailAcceptRequest = AuthVerifyEmailAcceptRequest(mockEmail, "wrongcode") + val verifyEmailAcceptRequest = AuthVerifyEmailAcceptRequest(mockEmail, "wrong_code") coEvery { authService.verifyAcceptSignup(verifyEmailAcceptRequest) } returns Response.error( 400, errorResponseBody @@ -189,7 +192,7 @@ class AuthServiceTest { @Test fun `should return response with error when request code is invalid for password reset`() = runBlocking { - val verifyEmailAcceptRequest = AuthVerifyEmailAcceptRequest(mockEmail, "wrongcode") + val verifyEmailAcceptRequest = AuthVerifyEmailAcceptRequest(mockEmail, "wrong_code") coEvery { authService.verifyAcceptPW(verifyEmailAcceptRequest) } returns Response.error( 400, errorResponseBody @@ -214,4 +217,5 @@ class AuthServiceTest { coVerify(exactly = 1) { authService.resetPassword(resetPasswordRequest) } assertFalse(response.isSuccessful) } + }