From 10669727f0604dab5846fa898e95f2b3b93deed7 Mon Sep 17 00:00:00 2001 From: Noor53 Date: Sat, 13 Sep 2025 20:07:16 +0530 Subject: [PATCH 1/2] Add JUnit tests for AccountService, TransactionService, and UserService --- .../finance/service/AccountServiceTest.java | 76 +++++++ .../service/TransactionServiceTest.java | 187 ++++++++++++++++++ .../finance/service/UserServiceTest.java | 70 +++++++ 3 files changed, 333 insertions(+) create mode 100644 core-banking-service/src/test/java/com/javatodev/finance/service/AccountServiceTest.java create mode 100644 core-banking-service/src/test/java/com/javatodev/finance/service/TransactionServiceTest.java create mode 100644 core-banking-service/src/test/java/com/javatodev/finance/service/UserServiceTest.java diff --git a/core-banking-service/src/test/java/com/javatodev/finance/service/AccountServiceTest.java b/core-banking-service/src/test/java/com/javatodev/finance/service/AccountServiceTest.java new file mode 100644 index 0000000..613ae58 --- /dev/null +++ b/core-banking-service/src/test/java/com/javatodev/finance/service/AccountServiceTest.java @@ -0,0 +1,76 @@ +package com.javatodev.finance.service; + +import com.javatodev.finance.exception.EntityNotFoundException; +import com.javatodev.finance.model.dto.BankAccount; +import com.javatodev.finance.model.dto.UtilityAccount; +import com.javatodev.finance.model.entity.BankAccountEntity; +import com.javatodev.finance.model.entity.UtilityAccountEntity; +import com.javatodev.finance.repository.BankAccountRepository; +import com.javatodev.finance.repository.UtilityAccountRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +class AccountServiceTest { + + private BankAccountRepository bankAccountRepository; + private UtilityAccountRepository utilityAccountRepository; + private AccountService accountService; + + @BeforeEach + void setUp() { + bankAccountRepository = mock(BankAccountRepository.class); + utilityAccountRepository = mock(UtilityAccountRepository.class); + accountService = new AccountService(bankAccountRepository, utilityAccountRepository); + } + + @Test + void readBankAccount_found() { + BankAccountEntity entity = new BankAccountEntity(); + entity.setNumber("123"); + when(bankAccountRepository.findByNumber("123")).thenReturn(java.util.Optional.of(entity)); + + BankAccount dto = accountService.readBankAccount("123"); + assertNotNull(dto); + } + + @Test + void readBankAccount_notFound() { + when(bankAccountRepository.findByNumber("123")).thenReturn(java.util.Optional.empty()); + assertThrows(EntityNotFoundException.class, () -> accountService.readBankAccount("123")); + } + + @Test + void readUtilityAccount_byProvider_found() { + UtilityAccountEntity entity = new UtilityAccountEntity(); + entity.setProviderName("ProviderA"); + when(utilityAccountRepository.findByProviderName("ProviderA")).thenReturn(java.util.Optional.of(entity)); + + UtilityAccount dto = accountService.readUtilityAccount("ProviderA"); + assertNotNull(dto); + } + + @Test + void readUtilityAccount_byProvider_notFound() { + when(utilityAccountRepository.findByProviderName("ProviderA")).thenReturn(java.util.Optional.empty()); + assertThrows(EntityNotFoundException.class, () -> accountService.readUtilityAccount("ProviderA")); + } + + @Test + void readUtilityAccount_byId_found() { + UtilityAccountEntity entity = new UtilityAccountEntity(); + entity.setId(1L); + when(utilityAccountRepository.findById(1L)).thenReturn(java.util.Optional.of(entity)); + + UtilityAccount dto = accountService.readUtilityAccount(1L); + assertNotNull(dto); + } + + @Test + void readUtilityAccount_byId_notFound() { + when(utilityAccountRepository.findById(1L)).thenReturn(java.util.Optional.empty()); + assertThrows(EntityNotFoundException.class, () -> accountService.readUtilityAccount(1L)); + } +} + diff --git a/core-banking-service/src/test/java/com/javatodev/finance/service/TransactionServiceTest.java b/core-banking-service/src/test/java/com/javatodev/finance/service/TransactionServiceTest.java new file mode 100644 index 0000000..d7cc984 --- /dev/null +++ b/core-banking-service/src/test/java/com/javatodev/finance/service/TransactionServiceTest.java @@ -0,0 +1,187 @@ +package com.javatodev.finance.service; + +import com.javatodev.finance.exception.EntityNotFoundException; +import com.javatodev.finance.exception.GlobalErrorCode; +import com.javatodev.finance.exception.InsufficientFundsException; +import com.javatodev.finance.model.TransactionType; +import com.javatodev.finance.model.dto.BankAccount; +import com.javatodev.finance.model.dto.UtilityAccount; +import com.javatodev.finance.model.dto.request.FundTransferRequest; +import com.javatodev.finance.model.dto.request.UtilityPaymentRequest; +import com.javatodev.finance.model.dto.response.FundTransferResponse; +import com.javatodev.finance.model.dto.response.UtilityPaymentResponse; +import com.javatodev.finance.model.entity.BankAccountEntity; +import com.javatodev.finance.model.entity.TransactionEntity; +import com.javatodev.finance.repository.BankAccountRepository; +import com.javatodev.finance.repository.TransactionRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import java.math.BigDecimal; +import java.util.Optional; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +class TransactionServiceTest { + private AccountService accountService; + private BankAccountRepository bankAccountRepository; + private TransactionRepository transactionRepository; + private TransactionService transactionService; + + @BeforeEach + void setUp() { + accountService = mock(AccountService.class); + bankAccountRepository = mock(BankAccountRepository.class); + transactionRepository = mock(TransactionRepository.class); + transactionService = new TransactionService(accountService, bankAccountRepository, transactionRepository); + } + + @Test + void fundTransfer_success() { + FundTransferRequest request = new FundTransferRequest(); + request.setFromAccount("A1"); + request.setToAccount("A2"); + request.setAmount(BigDecimal.valueOf(100)); + + BankAccount from = new BankAccount(); + from.setNumber("A1"); + from.setActualBalance(BigDecimal.valueOf(200)); + BankAccount to = new BankAccount(); + to.setNumber("A2"); + to.setActualBalance(BigDecimal.valueOf(50)); + + when(accountService.readBankAccount("A1")).thenReturn(from); + when(accountService.readBankAccount("A2")).thenReturn(to); + BankAccountEntity fromEntity = new BankAccountEntity(); + fromEntity.setNumber("A1"); + fromEntity.setActualBalance(BigDecimal.valueOf(200)); + BankAccountEntity toEntity = new BankAccountEntity(); + toEntity.setNumber("A2"); + toEntity.setActualBalance(BigDecimal.valueOf(50)); + when(bankAccountRepository.findByNumber("A1")).thenReturn(Optional.of(fromEntity)); + when(bankAccountRepository.findByNumber("A2")).thenReturn(Optional.of(toEntity)); + + FundTransferResponse response = transactionService.fundTransfer(request); + assertNotNull(response.getTransactionId()); + assertEquals("Transaction successfully completed", response.getMessage()); + } + + @Test + void fundTransfer_insufficientFunds() { + FundTransferRequest request = new FundTransferRequest(); + request.setFromAccount("A1"); + request.setToAccount("A2"); + request.setAmount(BigDecimal.valueOf(300)); + BankAccount from = new BankAccount(); + from.setNumber("A1"); + from.setActualBalance(BigDecimal.valueOf(200)); + BankAccount to = new BankAccount(); + to.setNumber("A2"); + to.setActualBalance(BigDecimal.valueOf(50)); + when(accountService.readBankAccount("A1")).thenReturn(from); + when(accountService.readBankAccount("A2")).thenReturn(to); + assertThrows(InsufficientFundsException.class, () -> transactionService.fundTransfer(request)); + } + + @Test + void fundTransfer_accountNotFound() { + FundTransferRequest request = new FundTransferRequest(); + request.setFromAccount("A1"); + request.setToAccount("A2"); + request.setAmount(BigDecimal.valueOf(100)); + when(accountService.readBankAccount("A1")).thenThrow(EntityNotFoundException.class); + assertThrows(EntityNotFoundException.class, () -> transactionService.fundTransfer(request)); + } + + @Test + void utilPayment_success() { + UtilityPaymentRequest request = new UtilityPaymentRequest(); + request.setAccount("A1"); + request.setProviderId(1L); + request.setAmount(BigDecimal.valueOf(50)); + request.setReferenceNumber("REF123"); + BankAccount from = new BankAccount(); + from.setNumber("A1"); + from.setActualBalance(BigDecimal.valueOf(100)); + UtilityAccount utility = new UtilityAccount(); + utility.setId(1L); + when(accountService.readBankAccount("A1")).thenReturn(from); + when(accountService.readUtilityAccount(1L)).thenReturn(utility); + BankAccountEntity fromEntity = new BankAccountEntity(); + fromEntity.setNumber("A1"); + fromEntity.setActualBalance(BigDecimal.valueOf(100)); + fromEntity.setAvailableBalance(BigDecimal.valueOf(100)); + when(bankAccountRepository.findByNumber("A1")).thenReturn(Optional.of(fromEntity)); + UtilityPaymentResponse response = transactionService.utilPayment(request); + assertNotNull(response.getTransactionId()); + assertEquals("Utility payment successfully completed", response.getMessage()); + } + + @Test + void utilPayment_insufficientFunds() { + UtilityPaymentRequest request = new UtilityPaymentRequest(); + request.setAccount("A1"); + request.setProviderId(1L); + request.setAmount(BigDecimal.valueOf(150)); + BankAccount from = new BankAccount(); + from.setNumber("A1"); + from.setActualBalance(BigDecimal.valueOf(100)); + when(accountService.readBankAccount("A1")).thenReturn(from); + assertThrows(InsufficientFundsException.class, () -> transactionService.utilPayment(request)); + } + + @Test + void utilPayment_accountNotFound() { + UtilityPaymentRequest request = new UtilityPaymentRequest(); + request.setAccount("A1"); + request.setProviderId(1L); + request.setAmount(BigDecimal.valueOf(50)); + when(accountService.readBankAccount("A1")).thenThrow(EntityNotFoundException.class); + assertThrows(EntityNotFoundException.class, () -> transactionService.utilPayment(request)); + } + + @Test + void internalFundTransfer_success() { + BankAccount from = new BankAccount(); + from.setNumber("A1"); + from.setActualBalance(BigDecimal.valueOf(200)); + BankAccount to = new BankAccount(); + to.setNumber("A2"); + to.setActualBalance(BigDecimal.valueOf(50)); + BankAccountEntity fromEntity = new BankAccountEntity(); + fromEntity.setNumber("A1"); + fromEntity.setActualBalance(BigDecimal.valueOf(200)); + fromEntity.setAvailableBalance(BigDecimal.valueOf(200)); + BankAccountEntity toEntity = new BankAccountEntity(); + toEntity.setNumber("A2"); + toEntity.setActualBalance(BigDecimal.valueOf(50)); + toEntity.setAvailableBalance(BigDecimal.valueOf(50)); + when(bankAccountRepository.findByNumber("A1")).thenReturn(Optional.of(fromEntity)); + when(bankAccountRepository.findByNumber("A2")).thenReturn(Optional.of(toEntity)); + String transactionId = transactionService.internalFundTransfer(from, to, BigDecimal.valueOf(100)); + assertNotNull(transactionId); + verify(bankAccountRepository, times(2)).save(any(BankAccountEntity.class)); + verify(transactionRepository, times(2)).save(any(TransactionEntity.class)); + } + + @Test + void internalFundTransfer_entityNotFound() { + BankAccount from = new BankAccount(); + from.setNumber("A1"); + BankAccount to = new BankAccount(); + to.setNumber("A2"); + when(bankAccountRepository.findByNumber("A1")).thenReturn(Optional.empty()); + assertThrows(EntityNotFoundException.class, () -> transactionService.internalFundTransfer(from, to, BigDecimal.valueOf(100))); + } + + @Test + void validateBalance_throwsException() { + BankAccount account = new BankAccount(); + account.setNumber("A1"); + account.setActualBalance(BigDecimal.valueOf(50)); + assertThrows(InsufficientFundsException.class, () -> { + transactionService.fundTransfer(new FundTransferRequest("A1", "A2", BigDecimal.valueOf(100))); + }); + } +} + diff --git a/core-banking-service/src/test/java/com/javatodev/finance/service/UserServiceTest.java b/core-banking-service/src/test/java/com/javatodev/finance/service/UserServiceTest.java new file mode 100644 index 0000000..0b355b6 --- /dev/null +++ b/core-banking-service/src/test/java/com/javatodev/finance/service/UserServiceTest.java @@ -0,0 +1,70 @@ +package com.javatodev.finance.service; + +import com.javatodev.finance.exception.EntityNotFoundException; +import com.javatodev.finance.model.dto.User; +import com.javatodev.finance.model.entity.UserEntity; +import com.javatodev.finance.model.mapper.UserMapper; +import com.javatodev.finance.repository.UserRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import java.util.Collections; +import java.util.Optional; +import java.util.List; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +class UserServiceTest { + private UserRepository userRepository; + private UserService userService; + private UserMapper userMapper; + + @BeforeEach + void setUp() { + userRepository = mock(UserRepository.class); + userService = new UserService(userRepository); + userMapper = spy(new UserMapper()); + // Inject the spy mapper if needed + userService = Mockito.spy(userService); + Mockito.doReturn(userMapper).when(userService).userMapper; + } + + @Test + void readUser_found() { + UserEntity entity = new UserEntity(); + entity.setIdentificationNumber("ID123"); + User userDto = new User(); + userDto.setIdentificationNumber("ID123"); + when(userRepository.findByIdentificationNumber("ID123")).thenReturn(Optional.of(entity)); + doReturn(userDto).when(userMapper).convertToDto(entity); + User result = userService.readUser("ID123"); + assertNotNull(result); + assertEquals("ID123", result.getIdentificationNumber()); + } + + @Test + void readUser_notFound() { + when(userRepository.findByIdentificationNumber("ID123")).thenReturn(Optional.empty()); + assertThrows(EntityNotFoundException.class, () -> userService.readUser("ID123")); + } + + @Test + void readUsers_success() { + UserEntity entity = new UserEntity(); + entity.setIdentificationNumber("ID123"); + List entities = Collections.singletonList(entity); + Page page = new PageImpl<>(entities); + User userDto = new User(); + userDto.setIdentificationNumber("ID123"); + when(userRepository.findAll(any(Pageable.class))).thenReturn(page); + doReturn(Collections.singletonList(userDto)).when(userMapper).convertToDtoList(entities); + List result = userService.readUsers(Pageable.unpaged()); + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals("ID123", result.get(0).getIdentificationNumber()); + } +} + From 4ba981a9ee8a69e3f30a948f06abb3cb7f0cb9b0 Mon Sep 17 00:00:00 2001 From: Noor53 Date: Sat, 13 Sep 2025 20:11:34 +0530 Subject: [PATCH 2/2] Clean up UserServiceTest: remove unused import and resolve warnings --- .../finance/service/UserServiceTest.java | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/core-banking-service/src/test/java/com/javatodev/finance/service/UserServiceTest.java b/core-banking-service/src/test/java/com/javatodev/finance/service/UserServiceTest.java index 0b355b6..cadd652 100644 --- a/core-banking-service/src/test/java/com/javatodev/finance/service/UserServiceTest.java +++ b/core-banking-service/src/test/java/com/javatodev/finance/service/UserServiceTest.java @@ -3,7 +3,6 @@ import com.javatodev.finance.exception.EntityNotFoundException; import com.javatodev.finance.model.dto.User; import com.javatodev.finance.model.entity.UserEntity; -import com.javatodev.finance.model.mapper.UserMapper; import com.javatodev.finance.repository.UserRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -11,35 +10,29 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; + import java.util.Collections; import java.util.Optional; import java.util.List; + import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; class UserServiceTest { private UserRepository userRepository; private UserService userService; - private UserMapper userMapper; @BeforeEach void setUp() { userRepository = mock(UserRepository.class); userService = new UserService(userRepository); - userMapper = spy(new UserMapper()); - // Inject the spy mapper if needed - userService = Mockito.spy(userService); - Mockito.doReturn(userMapper).when(userService).userMapper; } @Test void readUser_found() { UserEntity entity = new UserEntity(); entity.setIdentificationNumber("ID123"); - User userDto = new User(); - userDto.setIdentificationNumber("ID123"); when(userRepository.findByIdentificationNumber("ID123")).thenReturn(Optional.of(entity)); - doReturn(userDto).when(userMapper).convertToDto(entity); User result = userService.readUser("ID123"); assertNotNull(result); assertEquals("ID123", result.getIdentificationNumber()); @@ -57,14 +50,10 @@ void readUsers_success() { entity.setIdentificationNumber("ID123"); List entities = Collections.singletonList(entity); Page page = new PageImpl<>(entities); - User userDto = new User(); - userDto.setIdentificationNumber("ID123"); when(userRepository.findAll(any(Pageable.class))).thenReturn(page); - doReturn(Collections.singletonList(userDto)).when(userMapper).convertToDtoList(entities); List result = userService.readUsers(Pageable.unpaged()); assertNotNull(result); assertEquals(1, result.size()); assertEquals("ID123", result.get(0).getIdentificationNumber()); } } -