<div class="page">
<div class="cover text-center">
<img class="mx-auto" src=/itb/images/logo_mislata.png alt="logo">
# BankAccountServiceTest amb Mockito
<div class="text-end fit-content ms-auto my-3 mt-auto pt-3">
<p><strong>Autor:</strong> Joan Puigcerver Ibáñez</p>
<p><strong>Correu electrònic:</strong> j.puigcerveribanez@edu.gva.es</p>
<p><strong>Curs:</strong> 2024/2025</p>
</div>
<div>
<p class="fw-bold mb-0">Llicència: BY-NC-SA</p>
<p class="d-none d-md-block">(Reconeixement - No Comercial - Compartir Igual)</p>
<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.ca" target="_blank">
<img class="mx-auto" src="/itb/images/license.png" alt="Licence"/>
</a>
</div><!--license-->
</div><!--cover-->
</div><!--page-->
{:toc}
## Objectius
L'objectiu principal d'aquest exercici és posar en pràctica la creació de tests unitaris
utilitzant __objectes simulats__ amb la llibreria __Mockito__ en una aplicació
amb arquitectura per capes.
## Enunciat
Se'ns ha demanat crear una aplicació bancària per gestionar els comptes bancaris dels clients.
La nostra tasca consistirà en provar la funcionalitat de la classe `BankAccountServiceImpl` utilitzant tests unitaris i
objectes simulats utilitzant __Mockito__.
Les regles de negoci són les següents:
- Els comptes bancaris han de ser retornat ordenats pel número de compte bancari.
- La capa de serveis (`BankAccountService`) és la responsable de llançar les excepcions quan
la capa de persistència (`BankAccountRepository`) no pot trobar un compte bancari.
- El nom del titular del compte bancari ha de tenir com a mínim 3 caràcters.
- Quan s'actualitza el titular del compte bancari, s'ha de notificar al client.
## Codi Font
### Class [`BankAccount`](/DAM-ED/files/ud5/practices/bank/BankAccount.java)
```java
package ud5.practices.bank;
public class BankAccount {
private final String accountNumber;
private String accountHolder;
private double balance;
public BankAccount(String accountNumber, String accountHolder) {
this(accountNumber, accountHolder, 0.0);
}
public BankAccount(String accountNumber, String accountHolder, double initialBalance) {
this.accountNumber = accountNumber;
this.accountHolder = accountHolder;
this.balance = initialBalance;
}
public String getAccountNumber() {
return accountNumber;
}
public String getAccountHolder() {
return accountHolder;
}
public void setAccountHolder(String accountHolder) {
this.accountHolder = accountHolder;
}
public double getBalance() {
return balance;
}
public boolean deposit(double amount) {
if (amount > 0) {
balance += amount;
return true;
}
return false;
}
public boolean withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
return true;
}
return false;
}
public boolean transfer(BankAccount destination, double amount) {
boolean success = withdraw(amount);
if (success) {
destination.deposit(amount);
}
return success;
}
}
```
### Interface [`BankAccountService`](/DAM-ED/files/ud5/practices/bank/service/BankAccountService.java)
```java
package ud5.practices.bank.service;
import ud5.practices.bank.BankAccount;
import ud5.practices.bank.exception.BankAccountNotFoundException;
import ud5.practices.bank.exception.InvalidAccountHolderNameException;
import java.util.List;
public interface BankAccountService {
/**
* Get all bank accounts
* @return a list with all bank accounts
*/
List<BankAccount> getAll();
/**
* Get a bank account by its account number
* @param accountNumber the account number
* @return the bank account
* @throws BankAccountNotFoundException if does not exist a bank account with the given account number
*/
BankAccount getBankAccountByNumber(String accountNumber) throws BankAccountNotFoundException;
/**
* Update the account holder name of a bank account
* @param bankAccount the bank account
* @param accountHolder the new account holder name
* @throws InvalidAccountHolderNameException if the account holder name is invalid (less than 3 characters)
*/
void updateAccountHolder(BankAccount bankAccount, String accountHolder) throws InvalidAccountHolderNameException;
}
```
### Interface [`BankAccountRepository`](/DAM-ED/files/ud5/practices/bank/service/BankAccountRepository.java)
```java
package ud5.practices.bank.repository;
import ud5.practices.bank.BankAccount;
import java.util.List;
public interface BankAccountRepository {
/**
* Get all bank accounts
* @return a list with all bank accounts
*/
List<BankAccount> getAll();
/**
* Get a bank account by its account number
* @param accontNumber the account number
* @return the bank account; null if does not exist a bank account with the given account number
*/
BankAccount getBankAccountByNumber(String accontNumber);
/**
* Update the account holder name of a bank account
* @param bankAccount the bank account
*/
void updateAccountHolder(BankAccount bankAccount);
}
```
### Interface [`NotificationService`](/DAM-ED/files/ud5/practices/bank/service/NotificationService.java)
```java
package ud5.practices.bank.service;
import ud5.practices.bank.BankAccount;
public interface NotificationService {
/**
* Notify the change of the account holder name of a bank account
* @param bankAccount the bank account
*/
void notifyUpdateAccountHolderChange(BankAccount bankAccount);
}
```
### Exception [`BankAccountNotFoundException`](/DAM-ED/files/ud5/practices/bank/exception/BankAccountNotFoundException.java)
```java
package ud5.practices.bank.exception;
public class BankAccountNotFoundException extends Exception {
public BankAccountNotFoundException(String message){
super(message);
}
}
```
### Exception [`InvalidAccountHolderNameException`](/DAM-ED/files/ud5/practices/bank/exception/InvalidAccountHolderNameException.java)
```java
package ud5.practices.bank.exception;
public class InvalidAccountHolderNameException extends Exception {
public InvalidAccountHolderNameException(String message){
super(message);
}
}
```
### Class [`BankAccountServiceImpl`](/DAM-ED/files/ud5/practices/bank/service/BankAccountServiceImpl.java)
```java
package ud5.practices.bank.service.impl;
import ud5.practices.bank.BankAccount;
import ud5.practices.bank.exception.BankAccountNotFoundException;
import ud5.practices.bank.exception.InvalidAccountHolderNameException;
import ud5.practices.bank.repository.BankAccountRepository;
import ud5.practices.bank.service.BankAccountService;
import ud5.practices.bank.service.NotificationService;
import java.util.Comparator;
import java.util.List;
public class BankAccountServiceImpl implements BankAccountService {
private final BankAccountRepository bankAccountRepository;
private final NotificationService notificationService;
public BankAccountServiceImpl(BankAccountRepository bankAccountRepository, NotificationService notificationService) {
this.bankAccountRepository = bankAccountRepository;
this.notificationService = notificationService;
}
public List<BankAccount> getAll() {
List<BankAccount> bankAccounts = bankAccountRepository.getAll();
bankAccounts.sort(Comparator.comparing(BankAccount::getAccountNumber));
return bankAccounts;
}
public BankAccount getBankAccountByNumber(String accountNumber) throws BankAccountNotFoundException {
BankAccount bankAccount = bankAccountRepository.getBankAccountByNumber(accountNumber);
if (bankAccount == null) {
throw new BankAccountNotFoundException("Invalid account number: " + accountNumber);
}
return bankAccount;
}
public void updateAccountHolder(BankAccount bankAccount, String accountHolder) throws InvalidAccountHolderNameException {
if (bankAccount.getAccountHolder().length() < 3) {
throw new InvalidAccountHolderNameException("Holder name must be at least 3 characters long");
}
bankAccount.setAccountHolder(accountHolder);
notificationService.notifyUpdateAccountHolderChange(bankAccount);
bankAccountRepository.updateAccountHolder(bankAccount);
}
}
```
Aquest lloc web utilitza galetes per millorar l'experiència de l'usuari