From 661496a173b25ee51e94098499411076617b401c Mon Sep 17 00:00:00 2001 From: roost-io Date: Sat, 21 Mar 2026 12:48:50 +0000 Subject: [PATCH 1/4] Unit test generated by RoostGPT Using AI Model gpt-4.1 --- Online-Banking-App-Spring-Boot/pom.xml | 285 ++++++----- ...llerGetAccountTransactiontHistoryTest.java | 381 ++++++++++++++ .../AppControllerGetDashboardTest.java | 454 +++++++++++++++++ .../AppControllerGetPaymentHistoryTest.java | 359 ++++++++++++++ ...pControllerGetTransactiontHistoryTest.java | 468 ++++++++++++++++++ 5 files changed, 1833 insertions(+), 114 deletions(-) create mode 100644 Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetAccountTransactiontHistoryTest.java create mode 100644 Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetDashboardTest.java create mode 100644 Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetPaymentHistoryTest.java create mode 100644 Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetTransactiontHistoryTest.java diff --git a/Online-Banking-App-Spring-Boot/pom.xml b/Online-Banking-App-Spring-Boot/pom.xml index 2f14ebe..fdd1762 100644 --- a/Online-Banking-App-Spring-Boot/pom.xml +++ b/Online-Banking-App-Spring-Boot/pom.xml @@ -1,114 +1,171 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 2.7.15 - - - com.beko - DemoBank_v1 - 0.0.1-SNAPSHOT - DemoBank_v1 - Demo project for Spring Boot - - 1.8 - - - - org.springframework.boot - spring-boot-starter-data-jpa - - - org.springframework.boot - spring-boot-starter-mail - - - org.springframework.boot - spring-boot-starter-web - - - - com.mysql - mysql-connector-j - runtime - - - - org.springframework.boot - spring-boot-starter-tomcat - provided - - - org.springframework.boot - spring-boot-starter-test - test - - - javax.servlet - javax.servlet-api - 3.1.0 - - - - org.apache.tomcat.embed - tomcat-embed-jasper - provided - - - - org.springframework.boot - spring-boot-starter-validation - - - - javax.servlet.jsp - javax.servlet.jsp-api - 2.3.3 - provided - - - - javax.servlet - jstl - 1.2 - - - - org.springframework.security - spring-security-crypto - - - - io.jsonwebtoken - jjwt-api - 0.11.5 - - - - io.jsonwebtoken - jjwt-impl - 0.11.2 - runtime - - - - io.jsonwebtoken - jjwt-jackson - 0.11.2 - runtime - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.15 + + + + com.beko + DemoBank_v1 + 0.0.1-SNAPSHOT + DemoBank_v1 + Demo project for Spring Boot + + 1.8 + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-mail + + + org.springframework.boot + spring-boot-starter-web + + + com.mysql + mysql-connector-j + runtime + + + org.springframework.boot + spring-boot-starter-tomcat + provided + + + org.springframework.boot + spring-boot-starter-test + test + + + javax.servlet + javax.servlet-api + 3.1.0 + + + org.apache.tomcat.embed + tomcat-embed-jasper + provided + + + org.springframework.boot + spring-boot-starter-validation + + + javax.servlet.jsp + javax.servlet.jsp-api + 2.3.3 + provided + + + javax.servlet + jstl + 1.2 + + + org.springframework.security + spring-security-crypto + + + io.jsonwebtoken + jjwt-api + 0.11.5 + + + io.jsonwebtoken + jjwt-impl + 0.11.2 + runtime + + + io.jsonwebtoken + jjwt-jackson + 0.11.2 + runtime + + + org.mockito + mockito-junit-jupiter + 2.23.4 + test + + + + io.spring.javaformat + spring-javaformat-formatter + 0.0.40 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.jacoco + jacoco-maven-plugin + 0.8.11 + + + + prepare-agent + + + + report + test + + report + + + coverageReport + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.5 + + + + org.apache.maven.plugins + maven-surefire-report-plugin + 3.2.5 + + testReport + + + + + org.apache.maven.plugins + maven-site-plugin + 2.1 + + testReport + + + + + io.spring.javaformat + spring-javaformat-maven-plugin + 0.0.40 + + + + + + + + \ No newline at end of file diff --git a/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetAccountTransactiontHistoryTest.java b/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetAccountTransactiontHistoryTest.java new file mode 100644 index 0000000..77c7607 --- /dev/null +++ b/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetAccountTransactiontHistoryTest.java @@ -0,0 +1,381 @@ + +// ********RoostGPT******** +/* +Test generated by RoostGPT for test java-demo using AI Type Azure Open AI and AI Model gpt-4.1 + +ROOST_METHOD_HASH=getAccountTransactiontHistory_7bcb241fe3 +ROOST_METHOD_SIG_HASH=getAccountTransactiontHistory_8ce4880a24 + +Scenario 1: Valid Account ID Provided in Request + +Details: + TestName: validAccountIdReturnsTransactionHistory + Description: This test checks that when a valid 'account_id' is provided in the request map, the method fetches the corresponding transaction history and returns it inside a ResponseEntity with HTTP status 200 (OK). + +Execution: + Arrange: Create a request map with a valid numeric 'account_id' as a string. Mock the transactHistoryRepository to return a predefined, non-empty list of TransactionHistory objects when getTransactionRecordsByAccountId is called with this ID. + Act: Call getAccountTransactiontHistory with the prepared request map and a mock HttpSession object. + Assert: Assert that the ResponseEntity is not null, the status is OK, and the response body contains a map with the key "transaction_history" whose value matches the mocked list. + +Validation: + This test verifies that the method integrates request parsing, repository usage, and response creation correctly for standard cases, thereby ensuring basic functional correctness for typical user behavior. + + +Scenario 2: No Account ID Provided in Request Map + +Details: + TestName: missingAccountIdInRequestThrowsException + Description: This test examines the behavior when the request map does not contain the required 'account_id' key. It checks whether the method throws a NullPointerException, NumberFormatException, or any other exception due to the absence of the key. + +Execution: + Arrange: Prepare a request map without the 'account_id' key. Mock HttpSession as required. + Act: Invoke getAccountTransactiontHistory with this map and catch any thrown exception. + Assert: Assert that a NullPointerException occurs at the location where 'account_id' is accessed, or that another appropriate exception is thrown. + +Validation: + This test ensures that missing parameters are handled (by exception or otherwise). This is significant for robust input validation and reliability. + + +Scenario 3: Non-Numeric Account ID in Request Map + +Details: + TestName: nonNumericAccountIdThrowsNumberFormatException + Description: This test verifies the method’s response when a non-numeric value is given for 'account_id' in the request map, expecting a NumberFormatException when attempting to parse it to an int. + +Execution: + Arrange: Build a request map where 'account_id' is set to a non-numeric string (e.g., "abc"). + Act: Invoke getAccountTransactiontHistory and catch any NumberFormatException. + Assert: Assert that NumberFormatException is thrown. + +Validation: + The test confirms that the method strictly requires numeric 'account_id' values and fails otherwise, making it important for input validation. + + +Scenario 4: Account ID Maps to No Transaction History + +Details: + TestName: validAccountIdReturnsEmptyTransactionHistoryList + Description: This test evaluates the method's response when the 'account_id' exists but there are no transaction records associated with it. It checks that an empty list is returned under the "transaction_history" key. + +Execution: + Arrange: Use a request map with a valid numeric account_id. Mock transactHistoryRepository to return an empty list for this ID. + Act: Call getAccountTransactiontHistory using the prepared request map. + Assert: Assert that the returned map contains "transaction_history" with an empty list. + +Validation: + Verifies correct behavior for valid but unpopulated accounts, ensuring the API never fails for valid inputs and uses appropriate empty-collection semantics. + + +Scenario 5: Null Returned from Repository + +Details: + TestName: repositoryReturnsNullList + Description: This test explores the outcome if the transactHistoryRepository returns null for the transaction history list (not an empty list), emulating a potential repository layer bug or a scenario with a misconfigured repository. + +Execution: + Arrange: Set up the repository mock so getTransactionRecordsByAccountId returns null. Prepare a request map with a suitable account_id. + Act: Call getAccountTransactiontHistory with sample data. + Assert: Verify that the response is a map where "transaction_history" maps to null, or an exception is thrown if the implementation does not handle null. + +Validation: + Ensures system robustness in rare but possible repository misconfiguration cases and verifies how the method propagates or recovers from null repository returns. + + +Scenario 6: Repository Throws Exception + +Details: + TestName: repositoryThrowsExceptionPropagates + Description: This test checks whether the method properly propagates exceptions thrown by the transactHistoryRepository, such as runtime exceptions. + +Execution: + Arrange: Mock transactHistoryRepository.getTransactionRecordsByAccountId to throw an unchecked exception. Provide a valid request map with numeric account_id. + Act: Call getAccountTransactiontHistory and catch any exceptions. + Assert: Assert that the exception is thrown as expected. + +Validation: + This test is crucial for verifying that unexpected lower-layer failures are surfaced to higher layers for logging, error handling, or global exception mapping. + + +Scenario 7: Null Request Map Provided + +Details: + TestName: nullRequestMapThrowsException + Description: This test checks how the method behaves when the request map parameter itself is null, which should cause a NullPointerException when 'get' is called on the request map. + +Execution: + Arrange: Pass null as the request map to the method, with necessary mocks for other parameters. + Act: Invoke getAccountTransactiontHistory and catch exceptions. + Assert: Assert that a NullPointerException occurs. + +Validation: + Validates the method’s resilience to null inputs and enforces that callers must supply a non-null map. + + +Scenario 8: ResponseEntity Structure Verification + +Details: + TestName: responseEntityContainsExpectedKeys + Description: This test validates that the returned ResponseEntity contains exactly one key "transaction_history" in its map, and that the ResponseEntity is of the correct HTTP status. + +Execution: + Arrange: Prepare known request data and set up a mocked return list. + Act: Invoke the method. + Assert: Check that the returned response is a ResponseEntity, its statusCode is HttpStatus.OK, and the body map has only one key: "transaction_history". + +Validation: + Ensures the contract of the REST API is precisely implemented, which is critical for frontend/backend integration. + + +Scenario 9: HttpSession Parameter Is Null + +Details: + TestName: nullHttpSessionDoesNotAffectResult + Description: This test determines whether passing a null HttpSession (unused in the method body) has any bearing on the execution or result. + +Execution: + Arrange: Use a valid requestMap and pass null as the HttpSession parameter. + Act: Invoke getAccountTransactiontHistory. + Assert: Assert that the method executes without exception and returns the expected transaction history structure. + +Validation: + Assures future maintainers and clients that the session parameter, though present, is not required for operation, supporting flexible invocation. + + +Scenario 10: Large Transaction History List Returned + +Details: + TestName: largeTransactionHistoryReturnedCorrectly + Description: This test checks that the method can handle and correctly return very large lists of transaction history, testing potential performance or serialization-related boundaries. + +Execution: + Arrange: Mock transactHistoryRepository to return a very large list (e.g., thousands of TransactionHistory objects). Use a valid request map. + Act: Invoke getAccountTransactiontHistory. + Assert: Assert that the returned map's "transaction_history" key holds a list with all those items. + +Validation: + Confirms the scalability and stability of the endpoint in more demanding production-relevant scenarios. + + +*/ + +// ********RoostGPT******** + +package com.beko.DemoBank_v1.controllers; + +import com.beko.DemoBank_v1.models.TransactionHistory; +import com.beko.DemoBank_v1.repository.TransactHistoryRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import javax.servlet.http.HttpSession; +import java.util.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.anyInt; +import org.junit.jupiter.api.*; +import com.beko.DemoBank_v1.models.Account; +import com.beko.DemoBank_v1.models.PaymentHistory; +import com.beko.DemoBank_v1.models.User; +import com.beko.DemoBank_v1.repository.AccountRepository; +import com.beko.DemoBank_v1.repository.PaymentHistoryRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class AppControllerGetAccountTransactiontHistoryTest { + + private TransactHistoryRepository transactHistoryRepository; + + private AppController appController; + + @BeforeEach + void setUp() { + transactHistoryRepository = Mockito.mock(TransactHistoryRepository.class); + appController = new AppController(); + // Inject mock repository into AppController. Replace with real injection if + // necessary. + // TODO: If using dependency injection, update how the repository is set. + java.lang.reflect.Field repoField; + try { + repoField = AppController.class.getDeclaredField("transactHistoryRepository"); + repoField.setAccessible(true); + repoField.set(appController, transactHistoryRepository); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + @DisplayName("Valid Account ID Provided in Request returns transaction history") + @Tag("valid") + public void testValidAccountIdReturnsTransactionHistory() { + Map requestMap = new HashMap<>(); + int accountId = 123; // TODO: Change to desired valid account ID + requestMap.put("account_id", String.valueOf(accountId)); + List mockList = Arrays.asList(Mockito.mock(TransactionHistory.class), + Mockito.mock(TransactionHistory.class)); + Mockito.when(transactHistoryRepository.getTransactionRecordsByAccountId(accountId)).thenReturn(mockList); + ResponseEntity response = appController.getAccountTransactiontHistory(requestMap, + Mockito.mock(HttpSession.class)); + assertNotNull(response, "ResponseEntity should not be null"); + assertEquals(HttpStatus.OK, response.getStatusCode(), "Status code should be OK"); + Map body = (Map) response.getBody(); + assertNotNull(body, "Response body should not be null"); + assertTrue(body.containsKey("transaction_history"), "Key 'transaction_history' should exist"); + assertEquals(mockList, body.get("transaction_history"), "Returned list must match mocked list"); + } + + @Test + @DisplayName("No Account ID Provided in Request Map throws exception") + @Tag("invalid") + public void testMissingAccountIdInRequestThrowsException() { + Map requestMap = new HashMap<>(); + // Account ID is absent + Exception thrown = assertThrows(NullPointerException.class, () -> { + appController.getAccountTransactiontHistory(requestMap, Mockito.mock(HttpSession.class)); + }); + assertNotNull(thrown, "Exception should be thrown if 'account_id' key is missing"); + } + + @Test + @DisplayName("Non-Numeric Account ID in Request Map throws NumberFormatException") + @Tag("invalid") + public void testNonNumericAccountIdThrowsNumberFormatException() { + Map requestMap = new HashMap<>(); + requestMap.put("account_id", "abc"); + Exception thrown = assertThrows(NumberFormatException.class, () -> { + appController.getAccountTransactiontHistory(requestMap, Mockito.mock(HttpSession.class)); + }); + assertNotNull(thrown, "Exception should be thrown if 'account_id' is non-numeric"); + } + + @Test + @DisplayName("Account ID Maps to No Transaction History returns empty list") + @Tag("valid") + public void testValidAccountIdReturnsEmptyTransactionHistoryList() { + Map requestMap = new HashMap<>(); + int accountId = 789; // TODO: Change to valid account ID as needed + requestMap.put("account_id", String.valueOf(accountId)); + List emptyList = Collections.emptyList(); + Mockito.when(transactHistoryRepository.getTransactionRecordsByAccountId(accountId)).thenReturn(emptyList); + ResponseEntity response = appController.getAccountTransactiontHistory(requestMap, + Mockito.mock(HttpSession.class)); + assertNotNull(response, "ResponseEntity should not be null"); + assertEquals(HttpStatus.OK, response.getStatusCode(), "Status code should be OK"); + Map body = (Map) response.getBody(); + assertTrue(body.containsKey("transaction_history"), "Key 'transaction_history' should exist"); + assertEquals(emptyList, body.get("transaction_history"), "Returned list must be empty"); + } + + @Test + @DisplayName("Null Returned from Repository returns transaction_history as null") + @Tag("boundary") + public void testRepositoryReturnsNullList() { + Map requestMap = new HashMap<>(); + int accountId = 456; // TODO: Change to appropriate account ID + requestMap.put("account_id", String.valueOf(accountId)); + Mockito.when(transactHistoryRepository.getTransactionRecordsByAccountId(accountId)).thenReturn(null); + ResponseEntity response = appController.getAccountTransactiontHistory(requestMap, + Mockito.mock(HttpSession.class)); + assertNotNull(response, "ResponseEntity should not be null"); + Map body = (Map) response.getBody(); + assertTrue(body.containsKey("transaction_history"), "Key 'transaction_history' should exist"); + assertNull(body.get("transaction_history"), "Returned list should be null"); + } + + @Test + @DisplayName("Repository Throws Exception is propagated") + @Tag("integration") + public void testRepositoryThrowsExceptionPropagates() { + Map requestMap = new HashMap<>(); + int accountId = 888; // TODO: Modify as per test needs + requestMap.put("account_id", String.valueOf(accountId)); + Mockito.when(transactHistoryRepository.getTransactionRecordsByAccountId(accountId)) + .thenThrow(new RuntimeException("Repository failure")); + Exception thrown = assertThrows(RuntimeException.class, () -> { + appController.getAccountTransactiontHistory(requestMap, Mockito.mock(HttpSession.class)); + }); + assertEquals("Repository failure", thrown.getMessage(), "Exception message should propagate from repository"); + } + + @Test + @DisplayName("Null Request Map Provided throws exception") + @Tag("invalid") + public void testNullRequestMapThrowsException() { + assertThrows(NullPointerException.class, () -> { + appController.getAccountTransactiontHistory(null, Mockito.mock(HttpSession.class)); + }); + } + + @Test + @DisplayName("ResponseEntity Structure Verification") + @Tag("valid") + public void testResponseEntityContainsExpectedKeys() { + Map requestMap = new HashMap<>(); + int accountId = 321; // TODO: Use desired account ID + requestMap.put("account_id", String.valueOf(accountId)); + List mockList = Arrays.asList(Mockito.mock(TransactionHistory.class)); + Mockito.when(transactHistoryRepository.getTransactionRecordsByAccountId(accountId)).thenReturn(mockList); + ResponseEntity response = appController.getAccountTransactiontHistory(requestMap, + Mockito.mock(HttpSession.class)); + assertNotNull(response, "ResponseEntity should not be null"); + assertEquals(HttpStatus.OK, response.getStatusCode(), "Status code should be OK"); + Map body = (Map) response.getBody(); + assertNotNull(body, "Response body should be present"); + assertEquals(1, body.size(), "Response map should only have one key"); + assertTrue(body.containsKey("transaction_history"), + "Response map should contain only 'transaction_history' key"); + } + + @Test + @DisplayName("Null HttpSession Parameter does not affect result") + @Tag("boundary") + public void testNullHttpSessionDoesNotAffectResult() { + Map requestMap = new HashMap<>(); + int accountId = 654; // TODO: Change to a valid account ID + requestMap.put("account_id", String.valueOf(accountId)); + List mockList = Arrays.asList(Mockito.mock(TransactionHistory.class)); + Mockito.when(transactHistoryRepository.getTransactionRecordsByAccountId(accountId)).thenReturn(mockList); + ResponseEntity response = appController.getAccountTransactiontHistory(requestMap, null); + assertNotNull(response, "ResponseEntity should not be null when HttpSession is null"); + assertEquals(HttpStatus.OK, response.getStatusCode(), "Status code should be OK"); + Map body = (Map) response.getBody(); + assertNotNull(body, "Response body should exist"); + assertEquals(mockList, body.get("transaction_history"), "Returned list must match mocked list"); + } + + @Test + @DisplayName("Large Transaction History List Returned Correctly") + @Tag("boundary") + public void testLargeTransactionHistoryReturnedCorrectly() { + Map requestMap = new HashMap<>(); + int accountId = 999; // TODO: Change to desired large account ID + requestMap.put("account_id", String.valueOf(accountId)); + int largeCount = 5000; // Large size for boundary testing + List largeList = new ArrayList<>(); + for (int i = 0; i < largeCount; i++) { + largeList.add(Mockito.mock(TransactionHistory.class)); + } + Mockito.when(transactHistoryRepository.getTransactionRecordsByAccountId(accountId)).thenReturn(largeList); + ResponseEntity response = appController.getAccountTransactiontHistory(requestMap, + Mockito.mock(HttpSession.class)); + assertNotNull(response, "ResponseEntity should not be null"); + assertEquals(HttpStatus.OK, response.getStatusCode(), "Status code should be OK"); + Map body = (Map) response.getBody(); + assertNotNull(body, "Response body should exist"); + assertEquals(largeCount, body.get("transaction_history").size(), "Returned list must have all large items"); + assertEquals(largeList, body.get("transaction_history"), "Returned list must match mocked large list"); + } + +} \ No newline at end of file diff --git a/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetDashboardTest.java b/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetDashboardTest.java new file mode 100644 index 0000000..6d124f7 --- /dev/null +++ b/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetDashboardTest.java @@ -0,0 +1,454 @@ + +// ********RoostGPT******** +/* +Test generated by RoostGPT for test java-demo using AI Type Azure Open AI and AI Model gpt-4.1 + +ROOST_METHOD_HASH=getDashboard_b5ee2abfef +ROOST_METHOD_SIG_HASH=getDashboard_5168f207e9 + +Scenario 1: Dashboard Retrieval with Valid Session and User + +Details: + TestName: dashboardRetrievalWithValidSessionAndUser + Description: This test is meant to check if the getDashboard method returns a correct ResponseEntity when a valid HttpSession with a properly populated User attribute is provided. The scenario verifies the handling of expected normal input and ensures the returned response contains the user's accounts and total balance. + +Execution: + Arrange: Prepare a mock HttpSession with a User object whose user_id can be parsed as an integer. Mock the AccountRepository to return a list of Account objects and a BigDecimal balance for the given userId. + Act: Call getDashboard with the prepared session. + Assert: Confirm that the returned ResponseEntity is HTTP 200 OK, contains a Map with the keys "userAccounts" and "totalBalance", and the values match mocks. +Validation: + The assertion verifies that the method successfully assembles a user dashboard when the session is valid. This ensures primary business logic is correct for logged-in users. + + +Scenario 2: Dashboard Retrieval with Null User in Session + +Details: + TestName: dashboardRetrievalWithNullUserAttribute + Description: This test verifies the method's behavior when the session does not have a valid "user" attribute. It checks for robustness against missing session user context. + +Execution: + Arrange: Mock HttpSession to return null for getAttribute("user"). + Act: Call getDashboard with the session missing the user attribute. + Assert: Expect a NullPointerException or a ResponseEntity representing an error (as the method does not handle null user explicitly). +Validation: + The assertion confirms how the method reacts to a missing user—a critical scenario for session management and error handling. + + +Scenario 3: Dashboard Retrieval with Non-Integer User ID + +Details: + TestName: dashboardRetrievalWithNonIntegerUserId + Description: This scenario checks how the method handles a User object whose user_id is not convertible to integer (such as "abc", "", or null). It tests input validation robustness. + +Execution: + Arrange: Mock a User object whose user_id returns "abc" or empty string. Set up session to return this User. + Act: Invoke getDashboard. + Assert: Verify that a NumberFormatException is thrown. +Validation: + The assertion evaluates error resilience in user_id parsing, important for preventing crashes due to invalid data. + + +Scenario 4: Dashboard Retrieval with Empty Accounts List + +Details: + TestName: dashboardRetrievalWithEmptyAccountsList + Description: This test checks if the method successfully handles the case where the user's accounts list is empty. It ensures the response still contains the correct keys and a zero balance. + +Execution: + Arrange: Mock User with valid user_id. AccountRepository returns an empty list and a zero BigDecimal. + Act: Call getDashboard. + Assert: ResponseEntity body has "userAccounts" as empty list and "totalBalance" as zero. +Validation: + This assertion verifies the method properly handles users with no active accounts, supporting consistent UI/UX. + + +Scenario 5: Dashboard Retrieval with Null Balance + +Details: + TestName: dashboardRetrievalWithNullBalance + Description: This scenario assesses the response when AccountRepository returns null for totalBalance, simulating data access issues or uninitialized balances. + +Execution: + Arrange: Mock User, accounts list, and set totalBalance as null in accountRepository. + Act: Call getDashboard. + Assert: ResponseEntity body includes totalBalance as null. +Validation: + The assertion confirms the method propagates null values correctly, avoiding misplaced defaults that could mislead users. + + +Scenario 6: Dashboard Retrieval When AccountRepository Throws Exception + +Details: + TestName: dashboardRetrievalWithAccountRepositoryException + Description: This test validates the method's behavior when AccountRepository throws a runtime exception (e.g., database error), ensuring the controller's robustness in error scenarios. + +Execution: + Arrange: Mock session and User; configure AccountRepository to throw an exception when called. + Act: Call getDashboard. + Assert: Method propagates exception or returns an error ResponseEntity as per default Spring behavior. +Validation: + The assertion checks error propagation and handling, crucial for system reliability during infrastructure failures. + + +Scenario 7: Dashboard Retrieval with Multiple Accounts and Large Balance + +Details: + TestName: dashboardRetrievalWithMultipleAccountsAndLargeBalance + Description: This test assures that the method accurately handles and returns a list of multiple Account objects and a large balance, covering normal business use. + +Execution: + Arrange: Mock session/User; AccountRepository returns 3+ Account objects and a BigDecimal with a large value. + Act: Invoke getDashboard. + Assert: Confirm ResponseEntity contains all accounts and the large balance. +Validation: + This assertion confirms scalability and correctness in real-world scenarios with active users and significant funds. + + +Scenario 8: Dashboard Retrieval with User Having Negative Balance + +Details: + TestName: dashboardRetrievalWithNegativeBalance + Description: This scenario verifies proper handling of accounts with negative total balances, which may occur due to overdrafts. + +Execution: + Arrange: Mock User; AccountRepository returns accounts and a negative BigDecimal balance. + Act: Call getDashboard. + Assert: ResponseEntity shows correct negative totalBalance. +Validation: + The assertion ensures the system accurately reflects negative account states, vital for financial transparency. + + +Scenario 9: Dashboard Retrieval with Session Attribute “user” of Wrong Type + +Details: + TestName: dashboardRetrievalWithSessionUserOfIncorrectType + Description: Test checks how the method behaves if session attribute "user" is not a User object (e.g., a String or null), validating type safety. + +Execution: + Arrange: Set session attribute "user" to a String or an unrelated object. + Act: Call getDashboard. + Assert: Expect ClassCastException. +Validation: + The assertion validates robustness against session corruption or misconfiguration, reducing security risks. + + +Scenario 10: Dashboard Retrieval with User Having No user_id + +Details: + TestName: dashboardRetrievalWithUserMissingUserId + Description: This scenario tests the method's response when the User's user_id property is null, ensuring correct handling of incomplete data. + +Execution: + Arrange: Mock User with user_id as null; session returns this User. + Act: Invoke getDashboard. + Assert: NumberFormatException is thrown. +Validation: + The assertion checks defensive programming for user objects with missing identifiers, preventing ambiguous account access. + + +Scenario 11: Dashboard Retrieval with Session Timeout (Session Null) + +Details: + TestName: dashboardRetrievalWithNullSession + Description: Test verifies the controller's behavior when the HttpSession itself is null, simulating session timeout or invalid request. + +Execution: + Arrange: Call getDashboard with null for session. + Act: Invoke method. + Assert: NullPointerException is thrown, as session.getAttribute would fail. +Validation: + Confirms method sensitivity to session presence, important for request validation. + + +Scenario 12: Dashboard Retrieval with Accounts Repository Returning Null List + +Details: + TestName: dashboardRetrievalWithNullAccountsList + Description: This scenario examines the controller's resilience when the accountRepository.getUserAccountsById returns null, an unexpected null instead of a list. + +Execution: + Arrange: Mock User; configure AccountRepository to return null for getUserAccountsById. + Act: Invoke getDashboard. + Assert: ResponseEntity includes userAccounts as null. +Validation: + Ensures response is predictable even with repository edge-case returns, supporting robustness. + + +Scenario 13: Successful Dashboard Retrieval with User Having Single Account and Zero Balance + +Details: + TestName: dashboardRetrievalWithSingleAccountAndZeroBalance + Description: Test ensures correct response formation when user has a single account and a total balance of zero. + +Execution: + Arrange: Mock User; AccountRepository returns one account and zero balance. + Act: Call getDashboard. + Assert: ResponseEntity body contains the single account and zero balance. +Validation: + Confirms method accuracy for minimal, but not empty, account states. + + +Scenario 14: Dashboard Retrieval with User Having Special Characters in user_id + +Details: + TestName: dashboardRetrievalWithUserIdContainingSpecialCharacters + Description: Tests method’s response when the user_id contains special characters, ensuring that only valid numeric IDs are accepted. + +Execution: + Arrange: User object has user_id with special characters like "12!@#". + Act: Invoke getDashboard. + Assert: NumberFormatException is thrown. +Validation: + Validates input sanitation for user_id, crucial to prevent injection or parsing errors. + + +Scenario 15: Dashboard Retrieval with Large Account List + +Details: + TestName: dashboardRetrievalWithLargeAccountList + Description: Tests system performance and correctness with a large number of Account objects, simulating heavy users. + +Execution: + Arrange: Mock User; AccountRepository returns a list of hundreds of accounts. + Act: Call getDashboard. + Assert: ResponseEntity contains the full list with correct totalBalance. +Validation: + Confirms scalability and accurate aggregation for high-volume users. + +*/ + +// ********RoostGPT******** + +package com.beko.DemoBank_v1.controllers; + +import com.beko.DemoBank_v1.models.Account; +import com.beko.DemoBank_v1.models.User; +import com.beko.DemoBank_v1.repository.AccountRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.http.ResponseEntity; +import javax.servlet.http.HttpSession; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.*; +import com.beko.DemoBank_v1.models.PaymentHistory; +import com.beko.DemoBank_v1.models.TransactionHistory; +import com.beko.DemoBank_v1.repository.PaymentHistoryRepository; +import com.beko.DemoBank_v1.repository.TransactHistoryRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; + +@ExtendWith(MockitoExtension.class) +public class AppControllerGetDashboardTest { + + @Mock + private AccountRepository accountRepository; + + @Mock + private HttpSession session; + + @InjectMocks + private AppController appController; + + private User testUser; + + @BeforeEach + public void setUp() { + testUser = new User(); + } + + @Test + @Tag("valid") + public void testDashboardRetrievalWithValidSessionAndUser() { + testUser.setUser_id("1001"); + List dummyAccounts = new ArrayList<>(); + Account acc = new Account(); + // TODO: Set Account fields if needed + dummyAccounts.add(acc); + BigDecimal balance = new BigDecimal("1500.50"); + Mockito.when(session.getAttribute("user")).thenReturn(testUser); + Mockito.when(accountRepository.getUserAccountsById(1001)).thenReturn(dummyAccounts); + Mockito.when(accountRepository.getTotalBalance(1001)).thenReturn(balance); + ResponseEntity response = appController.getDashboard(session); + assertEquals(ResponseEntity.ok(getExpectedResponse(dummyAccounts, balance)), response); + } + + @Test + @Tag("invalid") + public void testDashboardRetrievalWithNullUserAttribute() { + Mockito.when(session.getAttribute("user")).thenReturn(null); + assertThrows(NullPointerException.class, () -> appController.getDashboard(session)); + } + + @Test + @Tag("invalid") + public void testDashboardRetrievalWithNonIntegerUserId() { + testUser.setUser_id("abc"); + Mockito.when(session.getAttribute("user")).thenReturn(testUser); + assertThrows(NumberFormatException.class, () -> appController.getDashboard(session)); + testUser.setUser_id(""); + Mockito.when(session.getAttribute("user")).thenReturn(testUser); + assertThrows(NumberFormatException.class, () -> appController.getDashboard(session)); + } + + @Test + @Tag("boundary") + public void testDashboardRetrievalWithEmptyAccountsList() { + testUser.setUser_id("2002"); + List emptyAccounts = new ArrayList<>(); + BigDecimal balance = BigDecimal.ZERO; + Mockito.when(session.getAttribute("user")).thenReturn(testUser); + Mockito.when(accountRepository.getUserAccountsById(2002)).thenReturn(emptyAccounts); + Mockito.when(accountRepository.getTotalBalance(2002)).thenReturn(balance); + ResponseEntity response = appController.getDashboard(session); + assertEquals(ResponseEntity.ok(getExpectedResponse(emptyAccounts, balance)), response); + } + + @Test + @Tag("invalid") + public void testDashboardRetrievalWithNullBalance() { + testUser.setUser_id("3003"); + List dummyAccounts = new ArrayList<>(); + dummyAccounts.add(new Account()); + // TODO: Set Account fields if needed + Mockito.when(session.getAttribute("user")).thenReturn(testUser); + Mockito.when(accountRepository.getUserAccountsById(3003)).thenReturn(dummyAccounts); + Mockito.when(accountRepository.getTotalBalance(3003)).thenReturn(null); + ResponseEntity response = appController.getDashboard(session); + assertEquals(ResponseEntity.ok(getExpectedResponse(dummyAccounts, null)), response); + } + + @Test + @Tag("invalid") + public void testDashboardRetrievalWithAccountRepositoryException() { + testUser.setUser_id("4004"); + Mockito.when(session.getAttribute("user")).thenReturn(testUser); + Mockito.when(accountRepository.getUserAccountsById(4004)).thenThrow(new RuntimeException("DB error")); + assertThrows(RuntimeException.class, () -> appController.getDashboard(session)); + } + + @Test + @Tag("valid") + public void testDashboardRetrievalWithMultipleAccountsAndLargeBalance() { + testUser.setUser_id("12345"); + List accounts = new ArrayList<>(); + for (int i = 0; i < 4; i++) + accounts.add(new Account()); + // TODO: Set Account fields if needed + BigDecimal balance = new BigDecimal("99999999.99"); + Mockito.when(session.getAttribute("user")).thenReturn(testUser); + Mockito.when(accountRepository.getUserAccountsById(12345)).thenReturn(accounts); + Mockito.when(accountRepository.getTotalBalance(12345)).thenReturn(balance); + ResponseEntity response = appController.getDashboard(session); + assertEquals(ResponseEntity.ok(getExpectedResponse(accounts, balance)), response); + } + + @Test + @Tag("valid") + public void testDashboardRetrievalWithNegativeBalance() { + testUser.setUser_id("8080"); + List accounts = new ArrayList<>(); + accounts.add(new Account()); + // TODO: Set Account fields if needed + BigDecimal negativeBalance = new BigDecimal("-250.00"); + Mockito.when(session.getAttribute("user")).thenReturn(testUser); + Mockito.when(accountRepository.getUserAccountsById(8080)).thenReturn(accounts); + Mockito.when(accountRepository.getTotalBalance(8080)).thenReturn(negativeBalance); + ResponseEntity response = appController.getDashboard(session); + assertEquals(ResponseEntity.ok(getExpectedResponse(accounts, negativeBalance)), response); + } + + @Test + @Tag("integration") + public void testDashboardRetrievalWithSessionUserOfIncorrectType() { + Mockito.when(session.getAttribute("user")).thenReturn("notAUser"); + assertThrows(ClassCastException.class, () -> appController.getDashboard(session)); + } + + @Test + @Tag("invalid") + public void testDashboardRetrievalWithUserMissingUserId() { + testUser.setUser_id(null); + Mockito.when(session.getAttribute("user")).thenReturn(testUser); + assertThrows(NumberFormatException.class, () -> appController.getDashboard(session)); + } + + @Test + @Tag("invalid") + public void testDashboardRetrievalWithNullSession() { + assertThrows(NullPointerException.class, () -> appController.getDashboard(null)); + } + + @Test + @Tag("invalid") + public void testDashboardRetrievalWithNullAccountsList() { + testUser.setUser_id("1010"); + Mockito.when(session.getAttribute("user")).thenReturn(testUser); + Mockito.when(accountRepository.getUserAccountsById(1010)).thenReturn(null); + Mockito.when(accountRepository.getTotalBalance(1010)).thenReturn(BigDecimal.ZERO); + ResponseEntity response = appController.getDashboard(session); + assertEquals(ResponseEntity.ok(getExpectedResponse(null, BigDecimal.ZERO)), response); + } + + @Test + @Tag("valid") + public void testDashboardRetrievalWithSingleAccountAndZeroBalance() { + testUser.setUser_id("3030"); + List accounts = new ArrayList<>(); + accounts.add(new Account()); + // TODO: Set Account fields if needed + BigDecimal balance = BigDecimal.ZERO; + Mockito.when(session.getAttribute("user")).thenReturn(testUser); + Mockito.when(accountRepository.getUserAccountsById(3030)).thenReturn(accounts); + Mockito.when(accountRepository.getTotalBalance(3030)).thenReturn(balance); + ResponseEntity response = appController.getDashboard(session); + assertEquals(ResponseEntity.ok(getExpectedResponse(accounts, balance)), response); + } + + @Test + @Tag("invalid") + public void testDashboardRetrievalWithUserIdContainingSpecialCharacters() { + testUser.setUser_id("12!@#"); + Mockito.when(session.getAttribute("user")).thenReturn(testUser); + assertThrows(NumberFormatException.class, () -> appController.getDashboard(session)); + } + + @Test + @Tag("valid") + public void testDashboardRetrievalWithLargeAccountList() { + testUser.setUser_id("5555"); + List accounts = new ArrayList<>(); + for (int i = 0; i < 250; i++) + accounts.add(new Account()); + // TODO: Set Account fields if needed + BigDecimal balance = new BigDecimal("50000.00"); + Mockito.when(session.getAttribute("user")).thenReturn(testUser); + Mockito.when(accountRepository.getUserAccountsById(5555)).thenReturn(accounts); + Mockito.when(accountRepository.getTotalBalance(5555)).thenReturn(balance); + ResponseEntity response = appController.getDashboard(session); + assertEquals(ResponseEntity.ok(getExpectedResponse(accounts, balance)), response); + } + + private Map getExpectedResponse(List userAccounts, BigDecimal totalBalance) { + Map response = new HashMap<>(); + response.put("userAccounts", userAccounts); + response.put("totalBalance", totalBalance); + return response; + } + +} \ No newline at end of file diff --git a/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetPaymentHistoryTest.java b/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetPaymentHistoryTest.java new file mode 100644 index 0000000..99cddb5 --- /dev/null +++ b/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetPaymentHistoryTest.java @@ -0,0 +1,359 @@ + +// ********RoostGPT******** +/* +Test generated by RoostGPT for test java-demo using AI Type Azure Open AI and AI Model gpt-4.1 + +ROOST_METHOD_HASH=getPaymentHistory_4e6e14afcb +ROOST_METHOD_SIG_HASH=getPaymentHistory_7e55128f09 + +Scenario 1: Valid user session with payment records present + +Details: + TestName: validUserSessionReturnsPaymentHistory + Description: This test verifies that when a valid user is present in the HttpSession and the PaymentHistoryRepository returns payment history records, the getPaymentHistory method responds with a ResponseEntity containing these records under the "payment_history" key. + +Execution: + Arrange: Mock HttpSession to return a User object with a valid user_id. Mock PaymentHistoryRepository to return a non-empty list of PaymentHistory objects for that userId. + Act: Invoke getPaymentHistory with the mocked session. + Assert: Check that the ResponseEntity status is OK, the body is a Map, and the "payment_history" key contains the expected PaymentHistory list. + +Validation: + This assertion verifies that the method behaves correctly for standard, successful usage and returns the correct data from the repository. It confirms the positive flow required for the application’s business logic. + + +Scenario 2: Valid user session with no payment records + +Details: + TestName: validUserSessionReturnsEmptyPaymentHistory + Description: This test ensures that when a user is present in the HttpSession but the PaymentHistoryRepository returns an empty list, the method responds with an empty "payment_history" list. + +Execution: + Arrange: Mock HttpSession to return a User object with a valid user_id. Mock PaymentHistoryRepository to return an empty list for that userId. + Act: Invoke getPaymentHistory with the mocked session. + Assert: Confirm that the ResponseEntity’s status is OK, the "payment_history" key exists in the body, and its value is an empty list. + +Validation: + This assertion confirms proper handling of edge cases where users have no payment history, preventing unexpected errors or null values in the response. + + +Scenario 3: Missing user in session + +Details: + TestName: sessionWithoutUserAttributeThrowsException + Description: This test checks that if the HttpSession does not contain a "user" attribute, the method throws a NullPointerException or handles it gracefully. + +Execution: + Arrange: Mock HttpSession to return null when getAttribute("user") is called. + Act: Invoke getPaymentHistory with the mocked session. + Assert: Detect if a NullPointerException is thrown, or check for graceful error handling. + +Validation: + Validates robust handling of unauthenticated access, an important security and stability requirement for web applications. + + +Scenario 4: User with invalid user_id (non-numeric) + +Details: + TestName: userWithNonNumericUserIdThrowsNumberFormatException + Description: This test ensures that if the User object’s user_id is not a valid number, the method throws a NumberFormatException. + +Execution: + Arrange: Mock HttpSession to return a User object with a non-numeric user_id (e.g., "abc"). + Act: Invoke getPaymentHistory with the mocked session. + Assert: Check that a NumberFormatException is thrown. + +Validation: + This verifies defensive programming and input validation within the method, preventing application crashes or data corruption. + + +Scenario 5: PaymentHistoryRepository throws exception + +Details: + TestName: paymentHistoryRepositoryThrowsExceptionIsPropagated + Description: This scenario checks if the PaymentHistoryRepository throws an exception during fetch, the method propagates or handles this exception appropriately. + +Execution: + Arrange: Mock HttpSession with a valid User object. Mock PaymentHistoryRepository.getPaymentsRecordsById to throw a RuntimeException. + Act: Invoke getPaymentHistory. + Assert: Confirm the exception is propagated and not swallowed, or observe graceful handling. + +Validation: + Handles repository-level failures securely, ensuring errors do not result in silent data loss and debugging remains possible. + + +Scenario 6: Response map contains only "payment_history" key + +Details: + TestName: responseContainsOnlyPaymentHistoryKey + Description: This test checks that the response map returned by getPaymentHistory contains only the "payment_history" key and no extra, unrelated data. + +Execution: + Arrange: Mock session with a valid User and PaymentHistoryRepository returning a sample list. + Act: Call getPaymentHistory. + Assert: Check that the response map contains a single key — "payment_history". + +Validation: + Ensures response data structure consistency for frontend consumption and contract correctness. + + +Scenario 7: Null PaymentHistory list returned from repository + +Details: + TestName: repositoryReturnsNullPaymentHistoryList + Description: This test verifies handling when PaymentHistoryRepository returns null instead of a list (an unlikely, but possible bug or misconfiguration). + +Execution: + Arrange: Mock HttpSession with valid User. Mock PaymentHistoryRepository.getPaymentsRecordsById to return null. + Act: Invoke getPaymentHistory. + Assert: Check if the response map value for "payment_history" is null or an empty list, and if a ResponseEntity is still returned with status OK. + +Validation: + Shows method resilience against unexpected external repository behaviors, ensuring front-end applications do not crash on nulls. + + +Scenario 8: User with a negative user_id + +Details: + TestName: userWithNegativeUserIdReturnsPaymentHistory + Description: This test confirms that if the user_id is negative, the method still executes and calls repository.getPaymentsRecordsById with the negative value, returning the corresponding repository result. + +Execution: + Arrange: Mock session with User whose user_id is a negative integer string (e.g., "-5"). Mock PaymentHistoryRepository to return a valid or empty list. + Act: Call getPaymentHistory. + Assert: The method returns a ResponseEntity with whatever repository provides, for the negative userId. + +Validation: + Checks whether the method supports edge-case user IDs and doesn’t fail unexpectedly, supporting potential business requirements. + + +Scenario 9: HttpSession returns User object with null user_id + +Details: + TestName: userWithNullUserIdThrowsException + Description: This scenario validates behavior when User.getUser_id() returns null, to check for NullPointerException or graceful error handling. + +Execution: + Arrange: Mock HttpSession with User object whose user_id is null. + Act: Call getPaymentHistory. + Assert: Observe if method throws NullPointerException or another exception. + +Validation: + Ensures method’s robustness against incomplete or corrupted User objects in session, important for application integrity. + + +Scenario 10: Large number of PaymentHistory entries + +Details: + TestName: userWithManyPaymentHistoryEntriesReturnsFullList + Description: This test verifies that the method can handle large lists from PaymentHistoryRepository and returns all entries in the response map. + +Execution: + Arrange: Mock session with valid User. Mock PaymentHistoryRepository to return a large list (e.g., several thousand entries). + Act: Invoke getPaymentHistory. + Assert: Response contains the full list of PaymentHistory entries with status OK. + +Validation: + Affirms performance and scalability of the method for power users or long-term account histories. + +*/ + +// ********RoostGPT******** + +package com.beko.DemoBank_v1.controllers; + +import com.beko.DemoBank_v1.models.PaymentHistory; +import com.beko.DemoBank_v1.models.User; +import com.beko.DemoBank_v1.repository.PaymentHistoryRepository; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.http.ResponseEntity; +import javax.servlet.http.HttpSession; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; +import org.junit.jupiter.api.*; +import com.beko.DemoBank_v1.models.Account; +import com.beko.DemoBank_v1.models.TransactionHistory; +import com.beko.DemoBank_v1.repository.AccountRepository; +import com.beko.DemoBank_v1.repository.TransactHistoryRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import java.math.BigDecimal; + +@ExtendWith(MockitoExtension.class) +class AppControllerGetPaymentHistoryTest { + + @Mock + private PaymentHistoryRepository paymentHistoryRepository; + + @Mock + private HttpSession session; + + @InjectMocks + private AppController appController; + + private User validUser; + + @BeforeEach + void setUp() { + validUser = new User(); + validUser.setUser_id("123"); + // TODO: Add any other User setup here if needed + } + + @Test + @Tag("valid") + public void testValidUserSessionReturnsPaymentHistory() { + List paymentList = new ArrayList<>(); + PaymentHistory p1 = new PaymentHistory(); + // TODO: Set up PaymentHistory attributes if needed + paymentList.add(p1); + when(session.getAttribute("user")).thenReturn(validUser); + when(paymentHistoryRepository.getPaymentsRecordsById(123)).thenReturn(paymentList); + ResponseEntity response = appController.getPaymentHistory(session); + assertEquals(ResponseEntity.ok().build().getStatusCode(), response.getStatusCode()); + assertTrue(response.getBody() instanceof Map); + Map body = (Map) response.getBody(); + assertTrue(body.containsKey("payment_history")); + assertEquals(paymentList, (List) body.get("payment_history")); + } + + @Test + @Tag("boundary") + public void testValidUserSessionReturnsEmptyPaymentHistory() { + List paymentList = new ArrayList<>(); + when(session.getAttribute("user")).thenReturn(validUser); + when(paymentHistoryRepository.getPaymentsRecordsById(123)).thenReturn(paymentList); + ResponseEntity response = appController.getPaymentHistory(session); + assertEquals(ResponseEntity.ok().build().getStatusCode(), response.getStatusCode()); + assertTrue(response.getBody() instanceof Map); + Map body = (Map) response.getBody(); + assertTrue(body.containsKey("payment_history")); + assertTrue(body.get("payment_history") instanceof List); + assertEquals(0, ((List) body.get("payment_history")).size()); + } + + @Test + @Tag("invalid") + public void testSessionWithoutUserAttributeThrowsException() { + when(session.getAttribute("user")).thenReturn(null); + Exception exception = assertThrows(NullPointerException.class, () -> { + appController.getPaymentHistory(session); + }); + assertNotNull(exception); + } + + @Test + @Tag("invalid") + public void testUserWithNonNumericUserIdThrowsNumberFormatException() { + User nonNumericUser = new User(); + nonNumericUser.setUser_id("abc"); + when(session.getAttribute("user")).thenReturn(nonNumericUser); + Exception exception = assertThrows(NumberFormatException.class, () -> { + appController.getPaymentHistory(session); + }); + assertNotNull(exception); + } + + @Test + @Tag("integration") + public void testPaymentHistoryRepositoryThrowsExceptionIsPropagated() { + when(session.getAttribute("user")).thenReturn(validUser); + when(paymentHistoryRepository.getPaymentsRecordsById(123)).thenThrow(new RuntimeException("Repo error")); + Exception exception = assertThrows(RuntimeException.class, () -> { + appController.getPaymentHistory(session); + }); + assertEquals("Repo error", exception.getMessage()); + } + + @Test + @Tag("valid") + public void testResponseContainsOnlyPaymentHistoryKey() { + List paymentList = new ArrayList<>(); + PaymentHistory p1 = new PaymentHistory(); + paymentList.add(p1); + when(session.getAttribute("user")).thenReturn(validUser); + when(paymentHistoryRepository.getPaymentsRecordsById(123)).thenReturn(paymentList); + ResponseEntity response = appController.getPaymentHistory(session); + assertTrue(response.getBody() instanceof Map); + Map body = (Map) response.getBody(); + assertEquals(1, body.size()); + assertTrue(body.containsKey("payment_history")); + } + + @Test + @Tag("boundary") + public void testRepositoryReturnsNullPaymentHistoryList() { + when(session.getAttribute("user")).thenReturn(validUser); + when(paymentHistoryRepository.getPaymentsRecordsById(123)).thenReturn(null); + ResponseEntity response = appController.getPaymentHistory(session); + assertEquals(ResponseEntity.ok().build().getStatusCode(), response.getStatusCode()); + assertTrue(response.getBody() instanceof Map); + Map body = (Map) response.getBody(); + assertTrue(body.containsKey("payment_history")); + assertNull(body.get("payment_history")); + } + + @Test + @Tag("boundary") + public void testUserWithNegativeUserIdReturnsPaymentHistory() { + User negativeUser = new User(); + negativeUser.setUser_id("-5"); + List paymentList = new ArrayList<>(); + PaymentHistory p1 = new PaymentHistory(); + paymentList.add(p1); + when(session.getAttribute("user")).thenReturn(negativeUser); + when(paymentHistoryRepository.getPaymentsRecordsById(-5)).thenReturn(paymentList); + ResponseEntity response = appController.getPaymentHistory(session); + assertEquals(ResponseEntity.ok().build().getStatusCode(), response.getStatusCode()); + assertTrue(response.getBody() instanceof Map); + Map body = (Map) response.getBody(); + assertEquals(paymentList, (List) body.get("payment_history")); + } + + @Test + @Tag("invalid") + public void testUserWithNullUserIdThrowsException() { + User nullIdUser = new User(); + nullIdUser.setUser_id(null); + when(session.getAttribute("user")).thenReturn(nullIdUser); + Exception exception = assertThrows(NullPointerException.class, () -> { + appController.getPaymentHistory(session); + }); + assertNotNull(exception); + } + + @Test + @Tag("integration") + public void testUserWithManyPaymentHistoryEntriesReturnsFullList() { + List paymentList = new ArrayList<>(); + int largeCount = 3000; // TODO: Adjust for desired test size + for (int i = 0; i < largeCount; i++) { + PaymentHistory p = new PaymentHistory(); + // TODO: Set up PaymentHistory attributes for each entry if needed + paymentList.add(p); + } + when(session.getAttribute("user")).thenReturn(validUser); + when(paymentHistoryRepository.getPaymentsRecordsById(123)).thenReturn(paymentList); + ResponseEntity response = appController.getPaymentHistory(session); + assertEquals(ResponseEntity.ok().build().getStatusCode(), response.getStatusCode()); + Map body = (Map) response.getBody(); + assertTrue(body.containsKey("payment_history")); + List resultList = (List) body.get("payment_history"); + assertEquals(largeCount, resultList.size()); + } + +} \ No newline at end of file diff --git a/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetTransactiontHistoryTest.java b/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetTransactiontHistoryTest.java new file mode 100644 index 0000000..06fe61b --- /dev/null +++ b/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetTransactiontHistoryTest.java @@ -0,0 +1,468 @@ + +// ********RoostGPT******** +/* +Test generated by RoostGPT for test java-demo using AI Type Azure Open AI and AI Model gpt-4.1 + +ROOST_METHOD_HASH=getTransactiontHistory_55c628de72 +ROOST_METHOD_SIG_HASH=getTransactiontHistory_29b1ff7483 + +Scenario 1: Valid User Session with Transaction History Present + +Details: + TestName: validSessionReturnsTransactionHistoryList + Description: This test ensures that when a valid user is stored in the session and the TransactHistoryRepository returns a non-empty list of TransactionHistory, the method correctly returns a ResponseEntity containing the transaction history list mapped under "transaction_history". +Execution: + Arrange: Mock a HttpSession with a valid User object and a user_id that can be parsed to integer. Mock TransactHistoryRepository to return a sample list of TransactionHistory for the given userId. + Act: Call getTransactiontHistory with the mocked session. + Assert: Assert that the ResponseEntity is OK status, contains a map, and under "transaction_history" key lists the expected TransactionHistory entries. +Validation: + The assertion checks that the method collects the user’s transaction history and returns it as an HTTP 200 response in the expected format. This is significant as it confirms positive flow and correct data mapping for authenticated users. + +Scenario 2: Valid User Session with Empty Transaction History + +Details: + TestName: validSessionReturnsEmptyTransactionHistory + Description: This test verifies that when a valid user is in the session but TransactHistoryRepository returns an empty list, the response still contains the "transaction_history" key with an empty list. +Execution: + Arrange: Mock a HttpSession with a valid User object. Mock TransactHistoryRepository to return an empty list for that userId. + Act: Invoke getTransactiontHistory with the prepared session. + Assert: Assert that ResponseEntity has OK status and the "transaction_history" value is an empty list. +Validation: + This verifies that the method gracefully handles users with no transaction history, returning an empty list rather than null or failing. Correct handling of empty data is vital for client UI logic. + +Scenario 3: User Attribute Missing from Session + +Details: + TestName: missingUserAttributeThrowsException + Description: This test scenario checks behaviour when the session does not contain a "user" attribute, ensuring the method throws a NullPointerException or similar due to attempt to cast a null object. +Execution: + Arrange: Mock a HttpSession with no "user" attribute set. Ensure TransactHistoryRepository is not called. + Act: Invoke getTransactiontHistory with that session. + Assert: Assert that a NullPointerException (or similar) is thrown when accessing user.getUser_id(). +Validation: + This highlights error handling for absent authentication. The method does not guard against null users, so this test verifies system fails fast, alerting developers of needed session validation. + +Scenario 4: User Present but user_id is Not a Valid Integer + +Details: + TestName: userIdNotIntegerThrowsNumberFormatException + Description: This scenario ensures the method fails when the user's user_id cannot be parsed as an integer, validating exception propagation. +Execution: + Arrange: Mock a User with a user_id value that cannot be parsed to Integer (e.g., "abc"). Set this User in the session. + Act: Call getTransactiontHistory with the session. + Assert: Assert that NumberFormatException is thrown during Integer.parseInt(user.getUser_id()). +Validation: + This confirms strict type requirements for user_id. The test is significant to catch misconfigured data and prevent silent failures or security issues. + +Scenario 5: TransactHistoryRepository Returns Null + +Details: + TestName: repositoryReturnsNullTransactionHistoryList + Description: Ensures the method handles cases when the repository returns null instead of a List, checking for NullPointerException or correct mapping. +Execution: + Arrange: Mock a valid User and session. Mock TransactHistoryRepository to return null for transaction records. + Act: Invoke getTransactiontHistory with session. + Assert: Assert that the response map contains "transaction_history" mapped to null or a NullPointerException occurs. +Validation: + Validates robustness in handling unexpected repository behaviors, which is important for stability especially when integrating with third-party or legacy data sources. + +Scenario 6: User Object with Null user_id Field + +Details: + TestName: userWithNullUserIdThrowsException + Description: Tests the case where the User object is present in session but user_id is null, checking for exception handling during Integer parsing. +Execution: + Arrange: Mock a User with null user_id and place in session. Ensure repository is not invoked. + Act: Invoke getTransactiontHistory with session. + Assert: Assert that NullPointerException or NumberFormatException is thrown as Integer.parseInt(null) is called. +Validation: + This ensures defensive programming for input data from session storage and points to areas needing null checks and validation logic. + +Scenario 7: User Object is of Wrong Type in Session + +Details: + TestName: sessionUserAttributeOfWrongTypeThrowsClassCastException + Description: Checks behaviour if the "user" attribute in session is set to an unexpected object type instead of User, expecting a ClassCastException. +Execution: + Arrange: Mock the session and set "user" attribute to some non-User object (such as a String or Integer). + Act: Call getTransactiontHistory with this session. + Assert: Assert that a ClassCastException is thrown during casting. +Validation: + Highlights type safety issues and verifies method properly fails when session data is corrupted or used incorrectly. + +Scenario 8: Response Map Contains Only One Key + +Details: + TestName: responseMapContainsOnlyTransactionHistoryKey + Description: Ensures that the response map returned contains only the "transaction_history" key and nothing else. +Execution: + Arrange: Prepare valid User and session, mock repository to return data. + Act: Call the method with session. + Assert: Assert that the response map has exactly one key "transaction_history". +Validation: + Confirms that extra or uneeded information is not included in the response, maintaining strict API contract for client consumption. + +Scenario 9: Multiple Calls for Different Sessions Yield Different Histories + +Details: + TestName: differentSessionsReturnDifferentTransactionHistories + Description: Confirms that calling the method with two different user sessions yields responses with correct and distinct transaction histories respective to each user. +Execution: + Arrange: Prepare two sessions with different User objects and user_id values. Mock repository to return distinct histories for each userId. + Act: Invoke getTransactiontHistory for both sessions separately. + Assert: Assert that both responses return correct transaction histories corresponding to respective users. +Validation: + Ensures multi-user separation and that session context is properly respected, which is essential for secure and correct multi-user systems. + +Scenario 10: User with Negative user_id + +Details: + TestName: userWithNegativeUserIdReturnsExpectedTransactionHistory + Description: Tests what happens when user_id is negative (e.g., "-1"), ensuring system still queries repository and returns whatever is provided. +Execution: + Arrange: User object with user_id="-1" in session; repository mocked to return a specific history. + Act: Call method. + Assert: Assert that response contains repository data for negative userId. +Validation: + Verifies corner-case numerical inputs, ensuring the method does not break on valid parseable but unexpected user id values. + +Scenario 11: Transaction History Includes Null Entries + +Details: + TestName: transactionHistoryListContainsNullEntries + Description: Tests method behaviour if the repository returns a list containing null-valued objects within transaction history. +Execution: + Arrange: Mock repository to return a list containing valid TransactionHistory objects and also null entries; session has valid User. + Act: Call method. + Assert: Assert that response map’s "transaction_history" contains null entries as present in repository output. +Validation: + Ensures there is no filtering or silent removal of null objects, which can be important for handling incomplete or corrupted data. + +Scenario 12: Successful ResponseEntity Structure and Status + +Details: + TestName: responseEntityReturnsHttpStatusOk + Description: Checks that ResponseEntity returned is of status HTTP 200 OK and of correct type. +Execution: + Arrange: Set up session with valid User; repository returns any non-empty list. + Act: Call getTransactiontHistory. + Assert: Assert that the ResponseEntity has status OK and its body is a Map. +Validation: + Validates compliance with API status and type conventions, confirming correct HTTP semantics for client-server communication. + +Scenario 13: Repository Throws Exception + +Details: + TestName: repositoryThrowsExceptionPropagated + Description: Ensures that if repository throws any exception during getTransactionRecordsById, it propagates and is not caught/suppressed. +Execution: + Arrange: Session with valid User; configure repository to throw an exception on retrieval. + Act: Call getTransactiontHistory. + Assert: Verify that the expected exception is thrown and not wrapped or handled silently. +Validation: + Confirms exception transparency, critical for debugging and for clients to understand real backend failures. + +Scenario 14: Session Contains Additional Attributes Not Used + +Details: + TestName: sessionWithExtraAttributesDoesNotAffectResponse + Description: Ensures that having additional unrelated attributes in session does not affect behaviour or result. +Execution: + Arrange: Session with valid User under "user" key; add other attributes with arbitrary content; repository returns valid list. + Act: Call getTransactiontHistory. + Assert: Assert that response is as expected, unaffected by other session attributes. +Validation: + Demonstrates method independence from session content beyond "user", ensuring predictable and stable behavior. + +Scenario 15: Response Map Type Is HashMap + +Details: + TestName: responseTypeIsHashMapWithListValue + Description: Confirms that the response map is always a HashMap, as per method logic. +Execution: + Arrange: Setup a valid session, repository returns any list. + Act: Invoke method. + Assert: Validate response body is instance of HashMap, and "transaction_history" value is an instance of List. +Validation: + This test is significant to ensure the API contract is fully respected regarding type safety and serialization. + + +*/ + +// ********RoostGPT******** + +package com.beko.DemoBank_v1.controllers; + +import com.beko.DemoBank_v1.models.User; +import com.beko.DemoBank_v1.models.TransactionHistory; +import com.beko.DemoBank_v1.repository.TransactHistoryRepository; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.*; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import javax.servlet.http.HttpSession; +import java.util.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; +import org.junit.jupiter.api.*; +import com.beko.DemoBank_v1.models.Account; +import com.beko.DemoBank_v1.models.PaymentHistory; +import com.beko.DemoBank_v1.repository.AccountRepository; +import com.beko.DemoBank_v1.repository.PaymentHistoryRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@ExtendWith(org.mockito.junit.jupiter.MockitoExtension.class) +public class AppControllerGetTransactiontHistoryTest { + + @InjectMocks + private AppController appController; + + @Mock + private TransactHistoryRepository transactHistoryRepository; + + @Mock + private HttpSession session; + + // Scenario 1: Valid User Session with Transaction History Present + @Test + @Tag("valid") + public void testValidSessionReturnsTransactionHistoryList() { + User mockUser = mock(User.class); + when(session.getAttribute("user")).thenReturn(mockUser); + when(mockUser.getUser_id()).thenReturn("101"); // TODO change for different user + List expectedHistory = Arrays.asList(mock(TransactionHistory.class), + mock(TransactionHistory.class)); + when(transactHistoryRepository.getTransactionRecordsById(101)).thenReturn(expectedHistory); + ResponseEntity response = appController.getTransactiontHistory(session); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertTrue(response.getBody() instanceof Map); + Map responseMap = (Map) response.getBody(); + assertTrue(responseMap.containsKey("transaction_history")); + assertEquals(expectedHistory, responseMap.get("transaction_history")); + } + + // Scenario 2: Valid User Session with Empty Transaction History + @Test + @Tag("boundary") + public void testValidSessionReturnsEmptyTransactionHistory() { + User mockUser = mock(User.class); + when(session.getAttribute("user")).thenReturn(mockUser); + when(mockUser.getUser_id()).thenReturn("102"); // TODO change as needed + List emptyHistory = Collections.emptyList(); + when(transactHistoryRepository.getTransactionRecordsById(102)).thenReturn(emptyHistory); + ResponseEntity response = appController.getTransactiontHistory(session); + assertEquals(HttpStatus.OK, response.getStatusCode()); + Map responseMap = (Map) response.getBody(); + assertTrue(responseMap.containsKey("transaction_history")); + assertTrue(((List) responseMap.get("transaction_history")).isEmpty()); + } + + // Scenario 3: User Attribute Missing from Session + @Test + @Tag("invalid") + public void testMissingUserAttributeThrowsException() { + when(session.getAttribute("user")).thenReturn(null); + assertThrows(NullPointerException.class, () -> { + appController.getTransactiontHistory(session); + }); + verify(transactHistoryRepository, never()).getTransactionRecordsById(anyInt()); + } + + // Scenario 4: User Present but user_id is Not a Valid Integer + @Test + @Tag("invalid") + public void testUserIdNotIntegerThrowsNumberFormatException() { + User mockUser = mock(User.class); + when(session.getAttribute("user")).thenReturn(mockUser); + when(mockUser.getUser_id()).thenReturn("abc"); // invalid int + assertThrows(NumberFormatException.class, () -> { + appController.getTransactiontHistory(session); + }); + verify(transactHistoryRepository, never()).getTransactionRecordsById(anyInt()); + } + + // Scenario 5: TransactHistoryRepository Returns Null + @Test + @Tag("boundary") + public void testRepositoryReturnsNullTransactionHistoryList() { + User mockUser = mock(User.class); + when(session.getAttribute("user")).thenReturn(mockUser); + when(mockUser.getUser_id()).thenReturn("103"); + when(transactHistoryRepository.getTransactionRecordsById(103)).thenReturn(null); + ResponseEntity response = appController.getTransactiontHistory(session); + assertEquals(HttpStatus.OK, response.getStatusCode()); + Map responseMap = (Map) response.getBody(); + assertTrue(responseMap.containsKey("transaction_history")); + assertNull(responseMap.get("transaction_history")); + } + + // Scenario 6: User Object with Null user_id Field + @Test + @Tag("invalid") + public void testUserWithNullUserIdThrowsException() { + User mockUser = mock(User.class); + when(session.getAttribute("user")).thenReturn(mockUser); + when(mockUser.getUser_id()).thenReturn(null); + assertThrows(NullPointerException.class, () -> { + appController.getTransactiontHistory(session); + }); + verify(transactHistoryRepository, never()).getTransactionRecordsById(anyInt()); + } + + // Scenario 7: User Object is of Wrong Type in Session + @Test + @Tag("invalid") + public void testSessionUserAttributeOfWrongTypeThrowsClassCastException() { + when(session.getAttribute("user")).thenReturn("notAUserObject"); + assertThrows(ClassCastException.class, () -> { + appController.getTransactiontHistory(session); + }); + verify(transactHistoryRepository, never()).getTransactionRecordsById(anyInt()); + } + + // Scenario 8: Response Map Contains Only One Key + @Test + @Tag("valid") + public void testResponseMapContainsOnlyTransactionHistoryKey() { + User mockUser = mock(User.class); + when(session.getAttribute("user")).thenReturn(mockUser); + when(mockUser.getUser_id()).thenReturn("104"); + List sampleHistory = Collections.singletonList(mock(TransactionHistory.class)); + when(transactHistoryRepository.getTransactionRecordsById(104)).thenReturn(sampleHistory); + ResponseEntity response = appController.getTransactiontHistory(session); + Map responseMap = (Map) response.getBody(); + assertEquals(1, responseMap.size()); + assertTrue(responseMap.containsKey("transaction_history")); + } + + // Scenario 9: Multiple Calls for Different Sessions Yield Different Histories + @Test + @Tag("integration") + public void testDifferentSessionsReturnDifferentTransactionHistories() { + User user1 = mock(User.class); + User user2 = mock(User.class); + HttpSession session1 = mock(HttpSession.class); + HttpSession session2 = mock(HttpSession.class); + when(session1.getAttribute("user")).thenReturn(user1); + when(session2.getAttribute("user")).thenReturn(user2); + when(user1.getUser_id()).thenReturn("201"); + when(user2.getUser_id()).thenReturn("202"); + List history1 = Arrays.asList(mock(TransactionHistory.class)); + List history2 = Arrays.asList(mock(TransactionHistory.class), + mock(TransactionHistory.class)); + when(transactHistoryRepository.getTransactionRecordsById(201)).thenReturn(history1); + when(transactHistoryRepository.getTransactionRecordsById(202)).thenReturn(history2); + ResponseEntity responseA = appController.getTransactiontHistory(session1); + ResponseEntity responseB = appController.getTransactiontHistory(session2); + Map mapA = (Map) responseA.getBody(); + Map mapB = (Map) responseB.getBody(); + assertEquals(history1, mapA.get("transaction_history")); + assertEquals(history2, mapB.get("transaction_history")); + assertNotEquals(mapA.get("transaction_history"), mapB.get("transaction_history")); + } + + // Scenario 10: User with Negative user_id + @Test + @Tag("boundary") + public void testUserWithNegativeUserIdReturnsExpectedTransactionHistory() { + User mockUser = mock(User.class); + when(session.getAttribute("user")).thenReturn(mockUser); + when(mockUser.getUser_id()).thenReturn("-1"); + List negativeHistory = Arrays.asList(mock(TransactionHistory.class)); + when(transactHistoryRepository.getTransactionRecordsById(-1)).thenReturn(negativeHistory); + ResponseEntity response = appController.getTransactiontHistory(session); + Map responseMap = (Map) response.getBody(); + assertEquals(negativeHistory, responseMap.get("transaction_history")); + } + + // Scenario 11: Transaction History Includes Null Entries + @Test + @Tag("boundary") + public void testTransactionHistoryListContainsNullEntries() { + User mockUser = mock(User.class); + when(session.getAttribute("user")).thenReturn(mockUser); + when(mockUser.getUser_id()).thenReturn("105"); + List historyWithNull = Arrays.asList(mock(TransactionHistory.class), null); + when(transactHistoryRepository.getTransactionRecordsById(105)).thenReturn(historyWithNull); + ResponseEntity response = appController.getTransactiontHistory(session); + Map responseMap = (Map) response.getBody(); + List actual = (List) responseMap.get("transaction_history"); + assertEquals(historyWithNull, actual); + assertTrue(actual.contains(null)); + } + + // Scenario 12: Successful ResponseEntity Structure and Status + @Test + @Tag("valid") + public void testResponseEntityReturnsHttpStatusOk() { + User mockUser = mock(User.class); + when(session.getAttribute("user")).thenReturn(mockUser); + when(mockUser.getUser_id()).thenReturn("106"); + List history = Arrays.asList(mock(TransactionHistory.class)); + when(transactHistoryRepository.getTransactionRecordsById(106)).thenReturn(history); + ResponseEntity response = appController.getTransactiontHistory(session); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertTrue(response.getBody() instanceof Map); + } + + // Scenario 13: Repository Throws Exception + @Test + @Tag("integration") + public void testRepositoryThrowsExceptionPropagated() { + User mockUser = mock(User.class); + when(session.getAttribute("user")).thenReturn(mockUser); + when(mockUser.getUser_id()).thenReturn("207"); + when(transactHistoryRepository.getTransactionRecordsById(207)) + .thenThrow(new RuntimeException("Test Exception")); + RuntimeException thrown = assertThrows(RuntimeException.class, () -> { + appController.getTransactiontHistory(session); + }); + assertEquals("Test Exception", thrown.getMessage()); + } + + // Scenario 14: Session Contains Additional Attributes Not Used + @Test + @Tag("valid") + public void testSessionWithExtraAttributesDoesNotAffectResponse() { + User mockUser = mock(User.class); + when(session.getAttribute("user")).thenReturn(mockUser); + when(mockUser.getUser_id()).thenReturn("303"); + List history = Arrays.asList(mock(TransactionHistory.class)); + when(transactHistoryRepository.getTransactionRecordsById(303)).thenReturn(history); + when(session.getAttribute("extra_attribute")).thenReturn("extra_value"); // this + // should + // not + // affect + // logic + ResponseEntity response = appController.getTransactiontHistory(session); + Map responseMap = (Map) response.getBody(); + assertEquals(history, responseMap.get("transaction_history")); + } + + // Scenario 15: Response Map Type Is HashMap + @Test + @Tag("valid") + public void testResponseTypeIsHashMapWithListValue() { + User mockUser = mock(User.class); + when(session.getAttribute("user")).thenReturn(mockUser); + when(mockUser.getUser_id()).thenReturn("404"); + List history = Arrays.asList(mock(TransactionHistory.class)); + when(transactHistoryRepository.getTransactionRecordsById(404)).thenReturn(history); + ResponseEntity response = appController.getTransactiontHistory(session); + assertTrue(response.getBody() instanceof HashMap); + Map responseMap = (Map) response.getBody(); + assertTrue(responseMap.get("transaction_history") instanceof List); + } + +} \ No newline at end of file From 2c6e45832cf9e2884069297eac176ff90fb45bed Mon Sep 17 00:00:00 2001 From: roost-io Date: Sun, 22 Mar 2026 03:53:12 +0000 Subject: [PATCH 2/4] Improved Unit test generated by RoostGPT Using AI Model gpt-4.1, for user feedback: Modify\sCode\sto\sfix\sthis\serror\nSuccessfully\scompiled\sbut\sfailed\sat\sruntime.\n\nError\sAnalysis:\n*What\sFailed:*\s\s\nUnit\stest\sexpecting\sNullPointerException\sactually\sreceived\sNumberFormatException.\n\n*Where:*\s\s\nAppControllerGetPaymentHistoryTest.testUserWithNullUserIdThrowsException\s(line\s159);\sroot\sat\sAppController.getPaymentHistory\s(line\s67).\n\n*Why:*\s\s\nNull\suser\sID\sinput\scaused\sInteger.parseInt(null),\swhich\sthrows\sNumberFormatException,\snot\sNullPointerException.\n\n*Investigate:*\s\s\nUpdate\stest\sto\sexpect\sNumberFormatException\sor\shandle\snull\suser\sID\smore\sgracefully\sin\sgetPaymentHistory\s(e.g.,\spre-check\sinput\sfor\snull,\sthrow\sa\scustom\sexception).\sReview\show\snulls\sare\sprocessed\sbefore\sparsing., --- .../AppControllerGetPaymentHistoryTest.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetPaymentHistoryTest.java b/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetPaymentHistoryTest.java index 99cddb5..04bab8c 100644 --- a/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetPaymentHistoryTest.java +++ b/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetPaymentHistoryTest.java @@ -155,6 +155,8 @@ Validation: Affirms performance and scalability of the method for power users or long-term account histories. + +roost_feedback [22/03/2026, 3:51:06 AM]:Modify\sCode\sto\sfix\sthis\serror\nSuccessfully\scompiled\sbut\sfailed\sat\sruntime.\n\nError\sAnalysis:\n*What\sFailed:*\s\s\nUnit\stest\sexpecting\sNullPointerException\sactually\sreceived\sNumberFormatException.\n\n*Where:*\s\s\nAppControllerGetPaymentHistoryTest.testUserWithNullUserIdThrowsException\s(line\s159);\sroot\sat\sAppController.getPaymentHistory\s(line\s67).\n\n*Why:*\s\s\nNull\suser\sID\sinput\scaused\sInteger.parseInt(null),\swhich\sthrows\sNumberFormatException,\snot\sNullPointerException.\n\n*Investigate:*\s\s\nUpdate\stest\sto\sexpect\sNumberFormatException\sor\shandle\snull\suser\sID\smore\sgracefully\sin\sgetPaymentHistory\s(e.g.,\spre-check\sinput\sfor\snull,\sthrow\sa\scustom\sexception).\sReview\show\snulls\sare\sprocessed\sbefore\sparsing., */ // ********RoostGPT******** @@ -211,7 +213,6 @@ class AppControllerGetPaymentHistoryTest { void setUp() { validUser = new User(); validUser.setUser_id("123"); - // TODO: Add any other User setup here if needed } @Test @@ -219,7 +220,6 @@ void setUp() { public void testValidUserSessionReturnsPaymentHistory() { List paymentList = new ArrayList<>(); PaymentHistory p1 = new PaymentHistory(); - // TODO: Set up PaymentHistory attributes if needed paymentList.add(p1); when(session.getAttribute("user")).thenReturn(validUser); when(paymentHistoryRepository.getPaymentsRecordsById(123)).thenReturn(paymentList); @@ -330,9 +330,9 @@ public void testUserWithNullUserIdThrowsException() { User nullIdUser = new User(); nullIdUser.setUser_id(null); when(session.getAttribute("user")).thenReturn(nullIdUser); - Exception exception = assertThrows(NullPointerException.class, () -> { - appController.getPaymentHistory(session); - }); + Exception exception = assertThrows(NumberFormatException.class, () -> { + appController.getPaymentHistory(session); + }); assertNotNull(exception); } @@ -340,10 +340,9 @@ public void testUserWithNullUserIdThrowsException() { @Tag("integration") public void testUserWithManyPaymentHistoryEntriesReturnsFullList() { List paymentList = new ArrayList<>(); - int largeCount = 3000; // TODO: Adjust for desired test size + int largeCount = 3000; for (int i = 0; i < largeCount; i++) { PaymentHistory p = new PaymentHistory(); - // TODO: Set up PaymentHistory attributes for each entry if needed paymentList.add(p); } when(session.getAttribute("user")).thenReturn(validUser); @@ -356,4 +355,4 @@ public void testUserWithManyPaymentHistoryEntriesReturnsFullList() { assertEquals(largeCount, resultList.size()); } -} \ No newline at end of file +} From e8b72d87f1af5e52d6839c0a9126c9457a8f44a8 Mon Sep 17 00:00:00 2001 From: roost-io Date: Wed, 25 Mar 2026 13:40:00 +0000 Subject: [PATCH 3/4] Improved Unit test generated by RoostGPT Using AI Model gpt-4.1, for user feedback: Modify\sCode\sto\sfix\sthis\serror\nSuccessfully\scompiled\sbut\sfailed\sat\sruntime.\n\nError\sAnalysis:\n*\sWhat\sFailed:\sTest\sexpected\sNullPointerException\sbut\sgot\sNumberFormatException\swhen\saccount\sID\sis\smissing.\n*\sWhere:\sAppControllerGetAccountTransactiontHistoryTest.java:79\s(calls\sAppController.getAccountTransactiontHistory,\sline\s104)\n*\sWhy:\sThe\scode\sattempts\sto\sparse\sa\snull\saccount\sID\sas\san\sinteger,\sresulting\sin\sNumberFormatException\sinstead\sof\sNullPointerException.\n*\sInvestigate:\sUpdate\seither\sthe\stest\sto\sexpect\sNumberFormatException\sor\sthe\scontroller\slogic\sto\sthrow\sNullPointerException\sas\sintended\swhen\saccount\sID\sis\smissing.\sReview\sinput\svalidation\sfor\saccount\sID\sin\sAppController.,\n\n\ndo\snot\sexpect\snull\sformat\sexception --- ...llerGetAccountTransactiontHistoryTest.java | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetAccountTransactiontHistoryTest.java b/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetAccountTransactiontHistoryTest.java index 77c7607..b569a4b 100644 --- a/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetAccountTransactiontHistoryTest.java +++ b/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetAccountTransactiontHistoryTest.java @@ -156,6 +156,8 @@ This test ensures that missing parameters are handled (by exception or otherwise Confirms the scalability and stability of the endpoint in more demanding production-relevant scenarios. + +roost_feedback [25/03/2026, 1:39:46 PM]:Modify\sCode\sto\sfix\sthis\serror\nSuccessfully\scompiled\sbut\sfailed\sat\sruntime.\n\nError\sAnalysis:\n*\sWhat\sFailed:\sTest\sexpected\sNullPointerException\sbut\sgot\sNumberFormatException\swhen\saccount\sID\sis\smissing.\n*\sWhere:\sAppControllerGetAccountTransactiontHistoryTest.java:79\s(calls\sAppController.getAccountTransactiontHistory,\sline\s104)\n*\sWhy:\sThe\scode\sattempts\sto\sparse\sa\snull\saccount\sID\sas\san\sinteger,\sresulting\sin\sNumberFormatException\sinstead\sof\sNullPointerException.\n*\sInvestigate:\sUpdate\seither\sthe\stest\sto\sexpect\sNumberFormatException\sor\sthe\scontroller\slogic\sto\sthrow\sNullPointerException\sas\sintended\swhen\saccount\sID\sis\smissing.\sReview\sinput\svalidation\sfor\saccount\sID\sin\sAppController.,\n\n\ndo\snot\sexpect\snull\sformat\sexception */ // ********RoostGPT******** @@ -202,9 +204,6 @@ class AppControllerGetAccountTransactiontHistoryTest { void setUp() { transactHistoryRepository = Mockito.mock(TransactHistoryRepository.class); appController = new AppController(); - // Inject mock repository into AppController. Replace with real injection if - // necessary. - // TODO: If using dependency injection, update how the repository is set. java.lang.reflect.Field repoField; try { repoField = AppController.class.getDeclaredField("transactHistoryRepository"); @@ -221,7 +220,7 @@ void setUp() { @Tag("valid") public void testValidAccountIdReturnsTransactionHistory() { Map requestMap = new HashMap<>(); - int accountId = 123; // TODO: Change to desired valid account ID + int accountId = 123; requestMap.put("account_id", String.valueOf(accountId)); List mockList = Arrays.asList(Mockito.mock(TransactionHistory.class), Mockito.mock(TransactionHistory.class)); @@ -241,7 +240,6 @@ public void testValidAccountIdReturnsTransactionHistory() { @Tag("invalid") public void testMissingAccountIdInRequestThrowsException() { Map requestMap = new HashMap<>(); - // Account ID is absent Exception thrown = assertThrows(NullPointerException.class, () -> { appController.getAccountTransactiontHistory(requestMap, Mockito.mock(HttpSession.class)); }); @@ -265,7 +263,7 @@ public void testNonNumericAccountIdThrowsNumberFormatException() { @Tag("valid") public void testValidAccountIdReturnsEmptyTransactionHistoryList() { Map requestMap = new HashMap<>(); - int accountId = 789; // TODO: Change to valid account ID as needed + int accountId = 789; requestMap.put("account_id", String.valueOf(accountId)); List emptyList = Collections.emptyList(); Mockito.when(transactHistoryRepository.getTransactionRecordsByAccountId(accountId)).thenReturn(emptyList); @@ -283,7 +281,7 @@ public void testValidAccountIdReturnsEmptyTransactionHistoryList() { @Tag("boundary") public void testRepositoryReturnsNullList() { Map requestMap = new HashMap<>(); - int accountId = 456; // TODO: Change to appropriate account ID + int accountId = 456; requestMap.put("account_id", String.valueOf(accountId)); Mockito.when(transactHistoryRepository.getTransactionRecordsByAccountId(accountId)).thenReturn(null); ResponseEntity response = appController.getAccountTransactiontHistory(requestMap, @@ -299,7 +297,7 @@ public void testRepositoryReturnsNullList() { @Tag("integration") public void testRepositoryThrowsExceptionPropagates() { Map requestMap = new HashMap<>(); - int accountId = 888; // TODO: Modify as per test needs + int accountId = 888; requestMap.put("account_id", String.valueOf(accountId)); Mockito.when(transactHistoryRepository.getTransactionRecordsByAccountId(accountId)) .thenThrow(new RuntimeException("Repository failure")); @@ -323,7 +321,7 @@ public void testNullRequestMapThrowsException() { @Tag("valid") public void testResponseEntityContainsExpectedKeys() { Map requestMap = new HashMap<>(); - int accountId = 321; // TODO: Use desired account ID + int accountId = 321; requestMap.put("account_id", String.valueOf(accountId)); List mockList = Arrays.asList(Mockito.mock(TransactionHistory.class)); Mockito.when(transactHistoryRepository.getTransactionRecordsByAccountId(accountId)).thenReturn(mockList); @@ -343,7 +341,7 @@ public void testResponseEntityContainsExpectedKeys() { @Tag("boundary") public void testNullHttpSessionDoesNotAffectResult() { Map requestMap = new HashMap<>(); - int accountId = 654; // TODO: Change to a valid account ID + int accountId = 654; requestMap.put("account_id", String.valueOf(accountId)); List mockList = Arrays.asList(Mockito.mock(TransactionHistory.class)); Mockito.when(transactHistoryRepository.getTransactionRecordsByAccountId(accountId)).thenReturn(mockList); @@ -360,9 +358,9 @@ public void testNullHttpSessionDoesNotAffectResult() { @Tag("boundary") public void testLargeTransactionHistoryReturnedCorrectly() { Map requestMap = new HashMap<>(); - int accountId = 999; // TODO: Change to desired large account ID + int accountId = 999; requestMap.put("account_id", String.valueOf(accountId)); - int largeCount = 5000; // Large size for boundary testing + int largeCount = 5000; List largeList = new ArrayList<>(); for (int i = 0; i < largeCount; i++) { largeList.add(Mockito.mock(TransactionHistory.class)); @@ -378,4 +376,4 @@ public void testLargeTransactionHistoryReturnedCorrectly() { assertEquals(largeList, body.get("transaction_history"), "Returned list must match mocked large list"); } -} \ No newline at end of file +} From 19b39712cc61667189cd2b94cc22a72758d7cc06 Mon Sep 17 00:00:00 2001 From: roost-io Date: Mon, 20 Apr 2026 11:58:32 +0000 Subject: [PATCH 4/4] Improved Unit test generated by RoostGPT Using AI Model gpt-4.1, for user feedback: add one more scenario for account holder --- .../AppControllerGetDashboardTest.java | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetDashboardTest.java b/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetDashboardTest.java index 6d124f7..1e79adc 100644 --- a/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetDashboardTest.java +++ b/Online-Banking-App-Spring-Boot/src/test/java/com/beko/DemoBank_v1/controllers/AppControllerGetDashboardTest.java @@ -215,6 +215,8 @@ Validation: Confirms scalability and accurate aggregation for high-volume users. + +roost_feedback [20/04/2026, 11:57:14 AM]:add one more scenario for account holder */ // ********RoostGPT******** @@ -278,7 +280,6 @@ public void testDashboardRetrievalWithValidSessionAndUser() { testUser.setUser_id("1001"); List dummyAccounts = new ArrayList<>(); Account acc = new Account(); - // TODO: Set Account fields if needed dummyAccounts.add(acc); BigDecimal balance = new BigDecimal("1500.50"); Mockito.when(session.getAttribute("user")).thenReturn(testUser); @@ -325,7 +326,6 @@ public void testDashboardRetrievalWithNullBalance() { testUser.setUser_id("3003"); List dummyAccounts = new ArrayList<>(); dummyAccounts.add(new Account()); - // TODO: Set Account fields if needed Mockito.when(session.getAttribute("user")).thenReturn(testUser); Mockito.when(accountRepository.getUserAccountsById(3003)).thenReturn(dummyAccounts); Mockito.when(accountRepository.getTotalBalance(3003)).thenReturn(null); @@ -349,7 +349,6 @@ public void testDashboardRetrievalWithMultipleAccountsAndLargeBalance() { List accounts = new ArrayList<>(); for (int i = 0; i < 4; i++) accounts.add(new Account()); - // TODO: Set Account fields if needed BigDecimal balance = new BigDecimal("99999999.99"); Mockito.when(session.getAttribute("user")).thenReturn(testUser); Mockito.when(accountRepository.getUserAccountsById(12345)).thenReturn(accounts); @@ -364,7 +363,6 @@ public void testDashboardRetrievalWithNegativeBalance() { testUser.setUser_id("8080"); List accounts = new ArrayList<>(); accounts.add(new Account()); - // TODO: Set Account fields if needed BigDecimal negativeBalance = new BigDecimal("-250.00"); Mockito.when(session.getAttribute("user")).thenReturn(testUser); Mockito.when(accountRepository.getUserAccountsById(8080)).thenReturn(accounts); @@ -411,7 +409,6 @@ public void testDashboardRetrievalWithSingleAccountAndZeroBalance() { testUser.setUser_id("3030"); List accounts = new ArrayList<>(); accounts.add(new Account()); - // TODO: Set Account fields if needed BigDecimal balance = BigDecimal.ZERO; Mockito.when(session.getAttribute("user")).thenReturn(testUser); Mockito.when(accountRepository.getUserAccountsById(3030)).thenReturn(accounts); @@ -435,7 +432,6 @@ public void testDashboardRetrievalWithLargeAccountList() { List accounts = new ArrayList<>(); for (int i = 0; i < 250; i++) accounts.add(new Account()); - // TODO: Set Account fields if needed BigDecimal balance = new BigDecimal("50000.00"); Mockito.when(session.getAttribute("user")).thenReturn(testUser); Mockito.when(accountRepository.getUserAccountsById(5555)).thenReturn(accounts); @@ -444,6 +440,24 @@ public void testDashboardRetrievalWithLargeAccountList() { assertEquals(ResponseEntity.ok(getExpectedResponse(accounts, balance)), response); } + @Test + @Tag("valid") + public void testDashboardRetrievalWithMultipleAccountHolders() { + User anotherUser = new User(); + anotherUser.setUser_id("1011"); + List accounts = new ArrayList<>(); + Account account1 = new Account(); + Account account2 = new Account(); + accounts.add(account1); + accounts.add(account2); + BigDecimal balance = new BigDecimal("3000.00"); + Mockito.when(session.getAttribute("user")).thenReturn(anotherUser); + Mockito.when(accountRepository.getUserAccountsById(1011)).thenReturn(accounts); + Mockito.when(accountRepository.getTotalBalance(1011)).thenReturn(balance); + ResponseEntity response = appController.getDashboard(session); + assertEquals(ResponseEntity.ok(getExpectedResponse(accounts, balance)), response); + } + private Map getExpectedResponse(List userAccounts, BigDecimal totalBalance) { Map response = new HashMap<>(); response.put("userAccounts", userAccounts); @@ -451,4 +465,4 @@ private Map getExpectedResponse(List userAccounts, BigD return response; } -} \ No newline at end of file +}