From 838751f0066d51d07105e4cf057710aa98a62eb9 Mon Sep 17 00:00:00 2001
From: Muhammad Raihan Akbar <ianakbar711@gmail.com>
Date: Thu, 6 Mar 2025 22:11:59 +0700
Subject: [PATCH] [REFACTOR] Fixed exception/logging maintainability issues

---
 .../service/GoogleAuthService.java            | 14 +--
 .../service/GoogleAuthServiceTest.java        | 93 +++++++++++++++----
 2 files changed, 84 insertions(+), 23 deletions(-)

diff --git a/src/main/java/com/safetypin/authentication/service/GoogleAuthService.java b/src/main/java/com/safetypin/authentication/service/GoogleAuthService.java
index 51a4a16..0fab533 100644
--- a/src/main/java/com/safetypin/authentication/service/GoogleAuthService.java
+++ b/src/main/java/com/safetypin/authentication/service/GoogleAuthService.java
@@ -136,10 +136,9 @@ public class GoogleAuthService {
         return tokenResponse.getAccessToken();
     }
 
-    String fetchUserData(String accessToken) throws IOException {
+    String fetchUserData(String accessToken) {
         try {
             String apiUrl = PEOPLE_API_BASE_URL + "?personFields=" + GoogleAuthService.BIRTHDAY;
-
             URL url = createURL(apiUrl);
 
             HttpURLConnection conn = (HttpURLConnection) url.openConnection();
@@ -153,14 +152,17 @@ public class GoogleAuthService {
                     return readResponse(conn.getInputStream());
                 } else {
                     logger.error("Error fetching data from Google API: HTTP {}", responseCode);
-                    throw new ApiException("Error fetching data from Google API");
+                    return null;
                 }
             } finally {
                 conn.disconnect();
             }
         } catch (MalformedURLException e) {
-            logger.error("Google authentication failed", e);
-            throw new IllegalArgumentException("Invalid API URL", e);
+            logger.error("Invalid API URL", e);
+            return null;
+        } catch (IOException e) {
+            logger.error("IO error when fetching user data", e);
+            return null;
         }
     }
 
@@ -176,7 +178,7 @@ public class GoogleAuthService {
         }
     }
 
-    LocalDate getUserBirthdate(String accessToken) throws IOException {
+    LocalDate getUserBirthdate(String accessToken) {
         String response = fetchUserData(accessToken);
         return extractBirthday(response);
     }
diff --git a/src/test/java/com/safetypin/authentication/service/GoogleAuthServiceTest.java b/src/test/java/com/safetypin/authentication/service/GoogleAuthServiceTest.java
index 797c159..23fcccd 100644
--- a/src/test/java/com/safetypin/authentication/service/GoogleAuthServiceTest.java
+++ b/src/test/java/com/safetypin/authentication/service/GoogleAuthServiceTest.java
@@ -1,5 +1,6 @@
 package com.safetypin.authentication.service;
 
+import ch.qos.logback.core.Appender;
 import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeTokenRequest;
 import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
 import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
@@ -12,18 +13,19 @@ import com.safetypin.authentication.model.User;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.Spy;
+import org.mockito.*;
 import org.mockito.junit.jupiter.MockitoExtension;
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.Appender;
+import org.slf4j.LoggerFactory;
 import org.springframework.test.util.ReflectionTestUtils;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
-import java.net.URL;
+import java.net.*;
 import java.time.LocalDate;
 import java.util.Optional;
 import java.util.UUID;
@@ -60,6 +62,12 @@ class GoogleAuthServiceTest {
     @InjectMocks
     private GoogleAuthService googleAuthService;
 
+    @Mock
+    private Appender<ILoggingEvent> mockAppender;
+
+    @Captor
+    private ArgumentCaptor<ILoggingEvent> loggingEventCaptor;
+
     private GoogleAuthDTO googleAuthDTO;
     private UUID testUserId;
 
@@ -79,6 +87,15 @@ class GoogleAuthServiceTest {
         googleAuthDTO.setServerAuthCode("test-auth-code");
 
         testUserId = UUID.randomUUID();
+        // Get Logback Logger
+        Logger root = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
+        root.setLevel(Level.INFO);
+
+        // Clear previous appenders to avoid duplicates
+        root.detachAndStopAllAppenders();
+
+        // Add mock appender
+        root.addAppender(mockAppender);
     }
 
     private void setPrivateField(Object instance, String fieldName, Object value) throws Exception {
@@ -386,10 +403,18 @@ class GoogleAuthServiceTest {
 
     @Test
     void testFetchUserData_ApiError() {
+        // Arrange & Act
+        String result = googleAuthService.fetchUserData(testAccessToken);
 
-        assertThrows(ApiException.class, () -> {
-            googleAuthService.fetchUserData(testAccessToken);
-        });
+        // Assert
+        assertNull(result);
+
+        // Verify logging occurred
+        verify(mockAppender).doAppend(loggingEventCaptor.capture());
+        ILoggingEvent loggingEvent = loggingEventCaptor.getValue();
+
+        assertEquals(Level.ERROR, loggingEvent.getLevel());
+        assertTrue(loggingEvent.getFormattedMessage().contains("Error fetching data from Google API"));
     }
 
     @Test
@@ -398,14 +423,48 @@ class GoogleAuthServiceTest {
         doThrow(new MalformedURLException("Invalid URL format"))
                 .when(googleAuthService).createURL(anyString());
 
-        // Act & Assert
-        IllegalArgumentException exception = assertThrows(
-                IllegalArgumentException.class,
-                () -> googleAuthService.fetchUserData(testAccessToken)
-        );
+        // Act
+        String result = googleAuthService.fetchUserData(testAccessToken);
+
+        // Assert
+        assertNull(result);
+
+        // Verify logging occurred
+        verify(mockAppender).doAppend(loggingEventCaptor.capture());
+        ILoggingEvent loggingEvent = loggingEventCaptor.getValue();
+
+        assertEquals(Level.ERROR, loggingEvent.getLevel());
+        assertTrue(loggingEvent.getFormattedMessage().contains("Invalid API URL"));
+    }
+
+    @Test
+    void testFetchUserData_IOException() {
+        // Create a test GoogleAuthService with a protected method for URL creation
+        GoogleAuthService spyService = spy(new GoogleAuthService(userService, jwtService) {
+            @Override
+            protected URL createURL(String urlString) throws IOException {
+                URL mockUrl = mock(URL.class);
+                HttpURLConnection mockConn = mock(HttpURLConnection.class);
 
-        // Verify the exception contains the expected message
-        assert(exception.getMessage().contains("Invalid API URL"));
-        assert(exception.getCause() instanceof MalformedURLException);
+                // Mock URL and connection behaviors
+                when(mockUrl.openConnection()).thenReturn(mockConn);
+                when(mockConn.getResponseCode()).thenThrow(new IOException("Network error"));
+
+                return mockUrl;
+            }
+        });
+
+        // Execute and verify
+        String response = spyService.fetchUserData(testAccessToken);
+        assertNull(response);
+
+        // Verify logging occurred
+        verify(mockAppender).doAppend(loggingEventCaptor.capture());
+        ILoggingEvent loggingEvent = loggingEventCaptor.getValue();
+
+        assertEquals(Level.ERROR, loggingEvent.getLevel());
+        assertTrue(loggingEvent.getFormattedMessage().contains("IO error when fetching user data"));
     }
+
+
 }
\ No newline at end of file
-- 
GitLab