From 0b8be4784d1ca283e67edf7863ceabb81f1733b6 Mon Sep 17 00:00:00 2001
From: KronosDP <darrel.danadyaksa19@gmail.com>
Date: Fri, 7 Mar 2025 09:39:37 +0700
Subject: [PATCH] [REFACTOR] Enhance OTPServiceTest with additional
 verification scenarios and null parameter checks

---
 .../service/OTPServiceTest.java               | 94 ++++++++++++++-----
 1 file changed, 73 insertions(+), 21 deletions(-)

diff --git a/src/test/java/com/safetypin/authentication/service/OTPServiceTest.java b/src/test/java/com/safetypin/authentication/service/OTPServiceTest.java
index 28d1e8d..d99e2b8 100644
--- a/src/test/java/com/safetypin/authentication/service/OTPServiceTest.java
+++ b/src/test/java/com/safetypin/authentication/service/OTPServiceTest.java
@@ -12,7 +12,8 @@ import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
 
 import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.when;
 
 @ExtendWith(MockitoExtension.class)
 class OTPServiceTest {
@@ -22,49 +23,100 @@ class OTPServiceTest {
     @Mock
     private EmailService emailService;
 
+    /**
+     * Helper method to generate an OTP different from the input
+     */
+    private String generateDifferentOTP(String originalOTP) {
+        if (originalOTP.equals("000000")) {
+            return "000001";
+        } else {
+            return "000000";
+        }
+    }
+
     @Test
     void testGenerateOTP() {
-        // Assume email service works
         when(emailService.sendOTPMail(anyString(), anyString()))
                 .thenReturn(CompletableFuture.completedFuture(true));
 
         String email = "user@example.com";
-        String otp = otpService.generateOTP(email);
-        assertNotNull(otp, "OTP should not be null");
-        assertEquals(6, otp.length(), "OTP should be 6 characters long");
-        assertTrue(otp.matches("\\d{6}"), "OTP should consist of 6 digits");
+        String generatedOTP = otpService.generateOTP(email);
 
-        // Verify emailService invoked once to send email
-        verify(emailService, times(1)).sendOTPMail(email, otp);
+        assertNotNull(generatedOTP, "Generated OTP should not be null");
+        assertEquals(6, generatedOTP.length(), "OTP should be 6 digits long");
     }
 
     @Test
-    void testVerifyOTPSuccess() {
+    void testVerifyOTPWrongOtp() {
         when(emailService.sendOTPMail(anyString(), anyString()))
                 .thenReturn(CompletableFuture.completedFuture(true));
 
         String email = "user@example.com";
-        String otp = otpService.generateOTP(email);
-        // Immediately verify the generated OTP; it should succeed.
-        boolean result = otpService.verifyOTP(email, otp);
-        assertTrue(result, "The OTP should verify successfully");
+        String generatedOTP = otpService.generateOTP(email);
+
+        // Generate a different OTP guaranteed to be different from the one generated
+        String wrongOTP = generateDifferentOTP(generatedOTP);
+
+        boolean result = otpService.verifyOTP(email, wrongOTP);
+        assertFalse(result, "Verification should fail for an incorrect OTP");
     }
 
-    // TODO: Test has a 1/1,000,000 chance to fail because OTP can generate all 0's.
     @Test
-    void testVerifyOTPWrongOtp() {
+    void testMultipleOTPGenerations() {
         when(emailService.sendOTPMail(anyString(), anyString()))
                 .thenReturn(CompletableFuture.completedFuture(true));
 
         String email = "user@example.com";
-        otpService.generateOTP(email);
-        // Try verifying with an incorrect OTP.
-        boolean result = otpService.verifyOTP(email, "000000");
-        assertFalse(result, "Verification should fail for an incorrect OTP");
+        String firstOTP = otpService.generateOTP(email);
+        String secondOTP = otpService.generateOTP(email);
+
+        assertNotEquals(firstOTP, secondOTP, "Generated OTPs should be different");
+    }
+
+    @Test
+    void testVerifyOTPAfterSecondGeneration() {
+        when(emailService.sendOTPMail(anyString(), anyString()))
+                .thenReturn(CompletableFuture.completedFuture(true));
+
+        String email = "user@example.com";
+        String firstOTP = otpService.generateOTP(email);
+        String secondOTP = otpService.generateOTP(email);
+
+        boolean result = otpService.verifyOTP(email, firstOTP);
+        assertFalse(result, "First OTP should not verify after second generation");
+
+        boolean secondResult = otpService.verifyOTP(email, secondOTP);
+        assertTrue(secondResult, "Latest OTP should verify successfully");
+    }
+
+    @Test
+    void testVerifyOTPMultipleTimes() {
+        when(emailService.sendOTPMail(anyString(), anyString()))
+                .thenReturn(CompletableFuture.completedFuture(true));
+
+        String email = "user@example.com";
+        String otp = otpService.generateOTP(email);
+
+        boolean firstTry = otpService.verifyOTP(email, otp);
+        assertTrue(firstTry, "First verification should succeed");
+
+        boolean secondTry = otpService.verifyOTP(email, otp);
+        assertFalse(secondTry, "Second verification should fail as OTP should be consumed");
+    }
+
+    @Test
+    void testNullParameters() {
+        assertThrows(NullPointerException.class, () -> {
+            otpService.verifyOTP(null, "123456");
+        }, "Should throw exception when email is null");
+
+        assertThrows(NullPointerException.class, () -> {
+            otpService.verifyOTP("user@example.com", null);
+        }, "Should throw exception when OTP is null");
     }
 
     @Test
-    void testVerifyOTPExpired() throws Exception {
+    void testOTPExpiration() throws Exception {
         when(emailService.sendOTPMail(anyString(), anyString()))
                 .thenReturn(CompletableFuture.completedFuture(true));
 
@@ -101,4 +153,4 @@ class OTPServiceTest {
         boolean result = otpService.verifyOTP("nonexistent@example.com", "123456");
         assertFalse(result, "Verification should fail when no OTP is generated for the given email");
     }
-}
+}
\ No newline at end of file
-- 
GitLab