From 2fc28411a83f4bfcd3a7e725d6ce725a5195cfc1 Mon Sep 17 00:00:00 2001
From: Muhammad Raihan Akbar <ianakbar711@gmail.com>
Date: Thu, 6 Mar 2025 21:04:18 +0700
Subject: [PATCH] [RED] Added JwtService Tests

---
 .../service/JwtServiceTest.java               | 156 ++++++++++++++++++
 1 file changed, 156 insertions(+)
 create mode 100644 src/test/java/com/safetypin/authentication/service/JwtServiceTest.java

diff --git a/src/test/java/com/safetypin/authentication/service/JwtServiceTest.java b/src/test/java/com/safetypin/authentication/service/JwtServiceTest.java
new file mode 100644
index 0000000..565497d
--- /dev/null
+++ b/src/test/java/com/safetypin/authentication/service/JwtServiceTest.java
@@ -0,0 +1,156 @@
+package com.safetypin.authentication.service;
+
+import com.safetypin.authentication.dto.UserResponse;
+import com.safetypin.authentication.exception.InvalidCredentialsException;
+import com.safetypin.authentication.model.User;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.JwtException;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import java.util.Date;
+import java.util.Optional;
+import java.util.UUID;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+public class JwtServiceTest {
+
+    @Mock
+    private UserService userService;
+
+    private JwtService jwtService;
+
+    private final String secretKey = "testSecretKeyWithAtLeast256BitsForHmacSha256Algorithm";
+    private final UUID userId = UUID.randomUUID();
+    private final User mockUser = mock(User.class);
+    private final UserResponse mockUserResponse = mock(UserResponse.class);
+
+    @BeforeEach
+    void setUp() {
+        // Create JwtService instance with the mocked UserService and test secret key
+        jwtService = new JwtService(secretKey, userService);
+    }
+
+    @Test
+    void constructor_shouldInitializeKeyAndUserService() {
+        // Verify constructor properly initializes the service
+        assertNotNull(jwtService);
+    }
+
+    @Test
+    void generateToken_shouldCreateValidJwt() {
+        // Generate a token
+        String token = jwtService.generateToken(userId);
+
+        // Verify token is not null or empty
+        assertNotNull(token);
+        assertFalse(token.isEmpty());
+
+        // Verify token can be parsed
+        Claims claims = jwtService.parseToken(token);
+        assertEquals(userId.toString(), claims.getSubject());
+        assertFalse(claims.getExpiration().before(new Date()));
+    }
+
+    @Test
+    void parseToken_shouldDecodeValidToken() {
+        // Generate a token
+        String token = jwtService.generateToken(userId);
+
+        // Parse the token
+        Claims claims = jwtService.parseToken(token);
+
+        // Verify claims
+        assertNotNull(claims);
+        assertEquals(userId.toString(), claims.getSubject());
+        assertNotNull(claims.getIssuedAt());
+        assertNotNull(claims.getExpiration());
+    }
+
+    @Test
+    void parseToken_shouldThrowExceptionForInvalidToken() {
+        // Invalid token
+        String invalidToken = "invalid.token.string";
+
+        // Verify exception is thrown
+        assertThrows(JwtException.class, () -> jwtService.parseToken(invalidToken));
+    }
+
+    @Test
+    void getUserFromJwtToken_shouldReturnUserForValidToken() throws InvalidCredentialsException {
+        // Set up mock responses
+        when(userService.findById(userId)).thenReturn(Optional.of(mockUser));
+        when(mockUser.generateUserResponse()).thenReturn(mockUserResponse);
+
+        // Generate a token
+        String token = jwtService.generateToken(userId);
+
+        // Get user from token
+        UserResponse response = jwtService.getUserFromJwtToken(token);
+
+        // Verify result
+        assertSame(mockUserResponse, response);
+        verify(userService).findById(userId);
+        verify(mockUser).generateUserResponse();
+    }
+
+    @Test
+    void getUserFromJwtToken_shouldThrowExceptionForExpiredToken() throws Exception {
+        // Create a JwtService with a custom expiration time
+        JwtService shortExpirationJwtService = new JwtService(secretKey, userService);
+
+        // Use reflection to create and set an expired token
+        String token = shortExpirationJwtService.generateToken(userId);
+        Claims claims = shortExpirationJwtService.parseToken(token);
+
+        // Create a new token with an expiration date in the past
+        Date pastDate = new Date(System.currentTimeMillis() - 1000); // 1 second in the past
+
+        // Use reflection to mock the parseToken method to return expired claims
+        JwtService spyService = spy(shortExpirationJwtService);
+        Claims expiredClaims = mock(Claims.class);
+        when(expiredClaims.getExpiration()).thenReturn(pastDate);
+        when(expiredClaims.getSubject()).thenReturn(userId.toString());
+        doReturn(expiredClaims).when(spyService).parseToken(anyString());
+
+        // Verify exception is thrown
+        InvalidCredentialsException exception = assertThrows(
+                InvalidCredentialsException.class,
+                () -> spyService.getUserFromJwtToken("expired-token")
+        );
+        assertEquals("Token expired", exception.getMessage());
+    }
+
+    @Test
+    void getUserFromJwtToken_shouldThrowExceptionWhenUserNotFound() {
+        // Set up mock to return empty optional
+        when(userService.findById(userId)).thenReturn(Optional.empty());
+
+        // Generate token
+        String token = jwtService.generateToken(userId);
+
+        // Verify exception is thrown
+        InvalidCredentialsException exception = assertThrows(
+                InvalidCredentialsException.class,
+                () -> jwtService.getUserFromJwtToken(token)
+        );
+        assertEquals("User not found", exception.getMessage());
+        verify(userService).findById(userId);
+    }
+
+    @Test
+    void getUserFromJwtToken_shouldHandleInvalidToken() {
+        // Invalid token
+        String invalidToken = "invalid.token.string";
+
+        // Verify exception is thrown
+        assertThrows(JwtException.class, () -> jwtService.getUserFromJwtToken(invalidToken));
+    }
+}
\ No newline at end of file
-- 
GitLab