diff --git a/pom.xml b/pom.xml index 2ca15ec..905522d 100644 --- a/pom.xml +++ b/pom.xml @@ -7,6 +7,43 @@ ch.engenius accounts 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + + + + org.projectlombok + lombok + 1.18.24 + provided + + + org.junit.jupiter + junit-jupiter-engine + 5.9.0-RC1 + + + org.mockito + mockito-junit-jupiter + 4.6.1 + compile + + + org.mockito + mockito-core + 4.6.1 + compile + + \ No newline at end of file diff --git a/src/main/java/ch/engenius/bank/Account.java b/src/main/java/ch/engenius/bank/Account.java deleted file mode 100644 index b9979cb..0000000 --- a/src/main/java/ch/engenius/bank/Account.java +++ /dev/null @@ -1,31 +0,0 @@ -package ch.engenius.bank; - -import java.math.BigDecimal; - -public class Account { - private double money; - - public void withdraw(double amount) { - if ((money - amount) < 0) { - throw new IllegalStateException("not enough credits on account"); - } - setMoney(money - amount); - - } - - public void deposit(double amount) { - setMoney(money + amount); - } - - public double getMoney() { - return money; - } - - public void setMoney(double money) { - this.money = money; - } - - public BigDecimal getMoneyAsBigDecimal() { - return BigDecimal.valueOf(money); - } -} diff --git a/src/main/java/ch/engenius/bank/Bank.java b/src/main/java/ch/engenius/bank/Bank.java deleted file mode 100644 index 571ebc7..0000000 --- a/src/main/java/ch/engenius/bank/Bank.java +++ /dev/null @@ -1,18 +0,0 @@ -package ch.engenius.bank; - -import java.util.HashMap; - -public class Bank { - private HashMap accounts = new HashMap<>(); - - public Account registerAccount(int accountNumber, int amount) { - Account account = new Account(); - account.setMoney(amount); - accounts.put(accountNumber, account); - return account; - } - - public Account getAccount( int number) { - return accounts.get(number); - } -} diff --git a/src/main/java/ch/engenius/bank/BankRunner.java b/src/main/java/ch/engenius/bank/BankRunner.java index 10b30fd..61dc726 100644 --- a/src/main/java/ch/engenius/bank/BankRunner.java +++ b/src/main/java/ch/engenius/bank/BankRunner.java @@ -1,5 +1,13 @@ package ch.engenius.bank; +import ch.engenius.bank.exception.AccountExistsException; +import ch.engenius.bank.exception.AccountNotFoundException; +import ch.engenius.bank.exception.IllegalAccountAmountException; +import ch.engenius.bank.model.Account; +import ch.engenius.bank.model.Bank; +import ch.engenius.bank.service.AccountService; +import ch.engenius.bank.service.BankService; + import java.math.BigDecimal; import java.util.Random; import java.util.concurrent.ExecutorService; @@ -12,60 +20,70 @@ public class BankRunner { private static final ExecutorService executor = Executors.newFixedThreadPool(8); private final Random random = new Random(43); - private final Bank bank = new Bank(); + private Bank bank = new Bank(); + private AccountService accountService = new AccountService(); + private final BankService bankService = new BankService(bank, accountService); public static void main(String[] args) { BankRunner runner = new BankRunner(); - int accounts = 100; - int defaultDeposit = 1000; - int iterations = 10000; - runner.registerAccounts(accounts, defaultDeposit); - runner.sanityCheck(accounts, accounts*defaultDeposit); - runner.runBank(iterations, accounts); - runner.sanityCheck(accounts, accounts*defaultDeposit); - + int accountsNumber = 100; + BigDecimal defaultDeposit = BigDecimal.valueOf(1000); + int iterations = 100000; + runner.registerAccounts(accountsNumber, defaultDeposit); + runner.sanityCheck(accountsNumber, BigDecimal.valueOf(accountsNumber).multiply(defaultDeposit)); + runner.runBank(iterations, accountsNumber); + runner.sanityCheck(accountsNumber, BigDecimal.valueOf(accountsNumber).multiply(defaultDeposit)); } private void runBank(int iterations, int maxAccount) { - for (int i =0; i< iterations; i++ ) { - executor.submit( ()-> runRandomOperation(maxAccount)); + for (int i = 0; i < iterations; i++) { + executor.submit(() -> runRandomOperation(maxAccount)); } try { executor.shutdown(); - executor.awaitTermination(100,TimeUnit.SECONDS); + executor.awaitTermination(100, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } } private void runRandomOperation(int maxAccount) { - double transfer = random.nextDouble()*100.0; + BigDecimal transferAmount = BigDecimal.valueOf(random.nextDouble() * 100.0); int accountInNumber = random.nextInt(maxAccount); int accountOutNumber = random.nextInt(maxAccount); - Account accIn =bank.getAccount(accountInNumber); - Account accOut =bank.getAccount(accountOutNumber); - accIn.deposit(transfer); - accOut.withdraw(transfer); + try { + bankService.transferMoney(accountInNumber, accountOutNumber, transferAmount); + } catch (AccountNotFoundException accountNotFoundException) { + System.out.println("Account with account number:" + accountNotFoundException.getAccountNumber()); + } catch (IllegalAccountAmountException illegalAccountAmountException) { + if (illegalAccountAmountException.getIllegalAmount().intValue() < 0) { + System.out.println("Amount for transfer can't be negative value"); + } else { + System.out.println("insufficient funds on account with account number:" + accountOutNumber); + } + } } - private void registerAccounts(int number, int defaultMoney) { - for ( int i = 0; i < number; i++) { - bank.registerAccount(i, defaultMoney); + private void registerAccounts(int number, BigDecimal defaultMoney) { + for (int i = 0; i < number; i++) { + try { + bankService.registerAccount(i, defaultMoney); + } catch (AccountExistsException accountExistsException) { + System.out.println("Account with account number:" + accountExistsException.getAccountNumber() + " already exist"); + } } } - private void sanityCheck( int accountMaxNumber, int totalExpectedMoney) { + private void sanityCheck(int accountMaxNumber, BigDecimal totalExpectedMoney) { BigDecimal sum = IntStream.range(0, accountMaxNumber) - .mapToObj( bank::getAccount) - .map ( Account::getMoneyAsBigDecimal) - .reduce( BigDecimal.ZERO, BigDecimal::add); + .mapToObj(bankService::getAccount) + .map(Account::getMoney) + .reduce(BigDecimal.ZERO, BigDecimal::add); - if ( sum.intValue() != totalExpectedMoney) { - throw new IllegalStateException("we got "+ sum + " != " + totalExpectedMoney +" (expected)"); + if (sum.compareTo(totalExpectedMoney) != 0) { + throw new IllegalStateException("we got " + sum + " != " + totalExpectedMoney + " (expected)"); } System.out.println("sanity check OK"); } - - } diff --git a/src/main/java/ch/engenius/bank/exception/AccountExistsException.java b/src/main/java/ch/engenius/bank/exception/AccountExistsException.java new file mode 100644 index 0000000..5440ec8 --- /dev/null +++ b/src/main/java/ch/engenius/bank/exception/AccountExistsException.java @@ -0,0 +1,10 @@ +package ch.engenius.bank.exception; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class AccountExistsException extends RuntimeException{ + private int accountNumber; +} diff --git a/src/main/java/ch/engenius/bank/exception/AccountNotFoundException.java b/src/main/java/ch/engenius/bank/exception/AccountNotFoundException.java new file mode 100644 index 0000000..7d16e26 --- /dev/null +++ b/src/main/java/ch/engenius/bank/exception/AccountNotFoundException.java @@ -0,0 +1,10 @@ +package ch.engenius.bank.exception; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class AccountNotFoundException extends RuntimeException{ + private int accountNumber; +} diff --git a/src/main/java/ch/engenius/bank/exception/IllegalAccountAmountException.java b/src/main/java/ch/engenius/bank/exception/IllegalAccountAmountException.java new file mode 100644 index 0000000..e851965 --- /dev/null +++ b/src/main/java/ch/engenius/bank/exception/IllegalAccountAmountException.java @@ -0,0 +1,12 @@ +package ch.engenius.bank.exception; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.math.BigDecimal; + +@AllArgsConstructor +@Getter +public class IllegalAccountAmountException extends RuntimeException { + private BigDecimal illegalAmount; +} diff --git a/src/main/java/ch/engenius/bank/model/Account.java b/src/main/java/ch/engenius/bank/model/Account.java new file mode 100644 index 0000000..7bc9866 --- /dev/null +++ b/src/main/java/ch/engenius/bank/model/Account.java @@ -0,0 +1,41 @@ +package ch.engenius.bank.model; + +import ch.engenius.bank.exception.IllegalAccountAmountException; +import lombok.*; + +import java.math.BigDecimal; +import java.util.concurrent.locks.ReentrantLock; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Account { + private BigDecimal money; + private int accountNumber; + private ReentrantLock lock; + + public void withdraw(BigDecimal amount) throws IllegalAccountAmountException { + validateWithdrawAmount(amount); + setMoney(money.subtract(amount)); + } + + public void lockAccount() { + this.lock.lock(); + } + + public void unlockAccount() { + this.lock.unlock(); + } + + public void deposit(BigDecimal amount) { + setMoney(money.add(amount)); + } + + private void validateWithdrawAmount(BigDecimal amount) { + if ((money.subtract(amount).compareTo(BigDecimal.ZERO)) < 0 || amount.compareTo(BigDecimal.ZERO) < 0) { + throw new IllegalAccountAmountException(amount); + } + } +} diff --git a/src/main/java/ch/engenius/bank/model/Bank.java b/src/main/java/ch/engenius/bank/model/Bank.java new file mode 100644 index 0000000..8859976 --- /dev/null +++ b/src/main/java/ch/engenius/bank/model/Bank.java @@ -0,0 +1,20 @@ +package ch.engenius.bank.model; + +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +@Getter +public class Bank { + private List accounts; + + public Bank(){ + this.accounts = new ArrayList<>(); + } + + public boolean addAccount(Account newAccount) { + return accounts.add(newAccount); + } + +} diff --git a/src/main/java/ch/engenius/bank/note b/src/main/java/ch/engenius/bank/note new file mode 100644 index 0000000..c7c9528 --- /dev/null +++ b/src/main/java/ch/engenius/bank/note @@ -0,0 +1,5 @@ +Another improvements that could be done is adding validation service layer, so for example we would have +BankServiceImplementaion and BankServiceValidation. Main benefit of this would be that our implementaion +service would we responsibility to only do business logic and not bothering with validation + +Another good improvement would be using one of the loggers(log4j probably) for logging certain events like creating accounts, transferring money etc. diff --git a/src/main/java/ch/engenius/bank/service/AccountService.java b/src/main/java/ch/engenius/bank/service/AccountService.java new file mode 100644 index 0000000..d436a81 --- /dev/null +++ b/src/main/java/ch/engenius/bank/service/AccountService.java @@ -0,0 +1,32 @@ +package ch.engenius.bank.service; + +import ch.engenius.bank.exception.IllegalAccountAmountException; +import ch.engenius.bank.model.Account; + +import java.math.BigDecimal; + +public class AccountService { + //Idea of adding AccountService was not to expose directly Account model to BankService. This approach is also good for unit testing, because + //AccountService will just be mocked and verified that is called. it's not a good idea to put synchronization in model, so AccountService is also + //Proxy to Account with responsibility of synchronization + + public void withdraw(Account account, BigDecimal amount) throws IllegalAccountAmountException { + try { + account.lockAccount(); + account.withdraw(amount); + } + finally { + account.unlockAccount(); + } + } + + public void deposit(Account account, BigDecimal amount) { + try { + account.lockAccount(); + account.deposit(amount); + } + finally { + account.unlockAccount(); + } + } +} diff --git a/src/main/java/ch/engenius/bank/service/BankService.java b/src/main/java/ch/engenius/bank/service/BankService.java new file mode 100644 index 0000000..7470d81 --- /dev/null +++ b/src/main/java/ch/engenius/bank/service/BankService.java @@ -0,0 +1,63 @@ +package ch.engenius.bank.service; + +import ch.engenius.bank.exception.AccountExistsException; +import ch.engenius.bank.exception.AccountNotFoundException; +import ch.engenius.bank.exception.IllegalAccountAmountException; +import ch.engenius.bank.model.Account; +import ch.engenius.bank.model.Bank; + +import java.math.BigDecimal; +import java.util.concurrent.locks.ReentrantLock; + +public class BankService { + + private Bank bank; + private AccountService accountService; + + public BankService(Bank bank, AccountService accountService) { + this.bank = bank; + this.accountService = accountService; + } + + public void transferMoney(int accOutNumber, int accInNumber, BigDecimal amount) throws AccountNotFoundException, IllegalAccountAmountException { + Account accIn = getAccount(accInNumber); //I have decided to not go for a synchronization here in this case, instead I choose to put it in Account service. + Account accOut = getAccount(accOutNumber); //If somebody implements another service that need to use our account withdraw and deposit methods, developer + accountService.withdraw(accOut, amount); //of that service must also deal with synchronization. In this way we are avoiding boilerplate code + accountService.deposit(accIn, amount); //and also preventing potential new bugs + } + + public Account getAccount(int accountNumber) throws AccountNotFoundException { + return bank.getAccounts().stream() + .filter(acc -> acc.getAccountNumber() == accountNumber) + .findFirst() + .orElseThrow(() -> new AccountNotFoundException(accountNumber)); + } + + public void registerAccount(int accountNumber, BigDecimal amount) throws AccountExistsException { + validateAccountExistence(accountNumber); + validateAmount(amount); + Account account = Account.builder() + .accountNumber(accountNumber) + .money(amount) + .lock(new ReentrantLock()) + .build(); + bank.addAccount(account); + } + + private void validateAmount(BigDecimal amount) { + if (amount.compareTo(BigDecimal.ZERO) < 0) { + throw new IllegalAccountAmountException(amount); + } + } + + private void validateAccountExistence(int accountNumber) { + if (accountExist(accountNumber)) { + throw new AccountExistsException(accountNumber); + } + } + + private boolean accountExist(int accountNumber) { + return bank.getAccounts().stream() + .anyMatch(acc -> acc.getAccountNumber() == accountNumber); + } +} diff --git a/src/main/java/ch/engenius/test/account/AccountServiceTest.java b/src/main/java/ch/engenius/test/account/AccountServiceTest.java new file mode 100644 index 0000000..6d4e311 --- /dev/null +++ b/src/main/java/ch/engenius/test/account/AccountServiceTest.java @@ -0,0 +1,41 @@ +package ch.engenius.test.account; + +import ch.engenius.bank.model.Account; +import ch.engenius.bank.service.AccountService; +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 java.math.BigDecimal; + +@ExtendWith(MockitoExtension.class) +public class AccountServiceTest { + private static final BigDecimal ACCOUNT_AMOUNT = BigDecimal.ONE; + + @Mock + private Account ACCOUNT; + + @InjectMocks + private AccountService accountService; + + @Test + public void withdraw_happyFlow() { + accountService.withdraw(ACCOUNT, ACCOUNT_AMOUNT); + + Mockito.verify(ACCOUNT).lockAccount(); + Mockito.verify(ACCOUNT).withdraw(ACCOUNT_AMOUNT); + Mockito.verify(ACCOUNT).unlockAccount(); + } + + @Test + public void deposit() { + accountService.deposit(ACCOUNT, ACCOUNT_AMOUNT); + + Mockito.verify(ACCOUNT).lockAccount(); + Mockito.verify(ACCOUNT).deposit(ACCOUNT_AMOUNT); + Mockito.verify(ACCOUNT).unlockAccount(); + } +} diff --git a/src/main/java/ch/engenius/test/account/AccountTest.java b/src/main/java/ch/engenius/test/account/AccountTest.java new file mode 100644 index 0000000..15877eb --- /dev/null +++ b/src/main/java/ch/engenius/test/account/AccountTest.java @@ -0,0 +1,70 @@ +package ch.engenius.test.account; + +import ch.engenius.bank.exception.IllegalAccountAmountException; +import ch.engenius.bank.model.Account; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.math.BigDecimal; +import java.util.concurrent.locks.ReentrantLock; + +import static org.junit.jupiter.api.Assertions.*; + +@ExtendWith(MockitoExtension.class) +public class AccountTest { + + private static final BigDecimal ACCOUNT_AMOUNT = BigDecimal.ONE; + private static final int ACCOUNT_NUMBER = 1; + + private Account account; + + @BeforeEach + public void setUp() { + this.account = Account.builder() + .money(ACCOUNT_AMOUNT) + .accountNumber(ACCOUNT_NUMBER) + .lock(new ReentrantLock()) + .build(); + } + + @Test + public void deposit_happyFlow() { + account.deposit(ACCOUNT_AMOUNT); + + assertEquals(BigDecimal.valueOf(2), account.getMoney()); + } + + @Test + public void withdraw_happyFlow() { + account.withdraw(ACCOUNT_AMOUNT); + + assertEquals(BigDecimal.ZERO, account.getMoney()); + } + + @Test + public void withdraw_notEnoughFunds_throwException() { + BigDecimal amountToWithdraw = BigDecimal.valueOf(2); + + IllegalAccountAmountException actualException = assertThrows(IllegalAccountAmountException.class, + () -> account.withdraw(amountToWithdraw)); + + assertEquals(amountToWithdraw, actualException.getIllegalAmount()); + } + + @Test + public void lockAccount_happyFlow() { + account.lockAccount(); + + assertTrue(account.getLock().isLocked()); + } + + @Test + public void unlockAccount_happyFlow() { + account.lockAccount(); + account.unlockAccount(); + + assertFalse(account.getLock().isLocked()); + } +} diff --git a/src/main/java/ch/engenius/test/bank/BankServiceTest.java b/src/main/java/ch/engenius/test/bank/BankServiceTest.java new file mode 100644 index 0000000..e665a32 --- /dev/null +++ b/src/main/java/ch/engenius/test/bank/BankServiceTest.java @@ -0,0 +1,131 @@ +package ch.engenius.test.bank; + +import ch.engenius.bank.exception.AccountExistsException; +import ch.engenius.bank.exception.AccountNotFoundException; +import ch.engenius.bank.exception.IllegalAccountAmountException; +import ch.engenius.bank.model.Account; +import ch.engenius.bank.model.Bank; +import ch.engenius.bank.service.AccountService; +import ch.engenius.bank.service.BankService; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.*; +import org.mockito.junit.jupiter.*; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@ExtendWith(MockitoExtension.class) +public class BankServiceTest { + + private static final int AMOUNT_ACCOUNT_NUMBER = 1; + private static final int NO_AMOUNT_ACCOUNT_NUMBER = 2; + private static final int NOT_EXISTING_ACCOUNT_NUMBER = 3; + private static final BigDecimal AMOUNT_ONE = BigDecimal.ONE; + private static final BigDecimal AMOUNT_ZERO = BigDecimal.ZERO; + private static final Account AMOUNT_ACCOUNT = Account.builder() + .money(AMOUNT_ONE) + .accountNumber(AMOUNT_ACCOUNT_NUMBER) + .build(); + private static final Account NO_AMOUNT_ACCOUNT = Account.builder() + .money(AMOUNT_ZERO) + .accountNumber(NO_AMOUNT_ACCOUNT_NUMBER) + .build(); + @Captor + private ArgumentCaptor accountCaptor; + + @Mock + private Bank bank; + @Mock + private AccountService accountService; + + @InjectMocks + private BankService bankService = new BankService(bank, accountService); + + @Test + public void transferMoney_happyFlow() { + Mockito.when(bank.getAccounts()).thenReturn(Arrays.asList(AMOUNT_ACCOUNT, NO_AMOUNT_ACCOUNT)); + + bankService.transferMoney(AMOUNT_ACCOUNT_NUMBER, NO_AMOUNT_ACCOUNT_NUMBER, AMOUNT_ONE); + + Mockito.verify(accountService).withdraw(AMOUNT_ACCOUNT, AMOUNT_ONE); + Mockito.verify(accountService).deposit(NO_AMOUNT_ACCOUNT, AMOUNT_ONE); + } + + @Test + public void transferMoney_accountDoesNotExist_throwsException(){ + Mockito.when(bank.getAccounts()).thenReturn(Arrays.asList(AMOUNT_ACCOUNT, NO_AMOUNT_ACCOUNT)); + + AccountNotFoundException actualException = assertThrows(AccountNotFoundException.class, + ()-> bankService.transferMoney( NO_AMOUNT_ACCOUNT_NUMBER,NOT_EXISTING_ACCOUNT_NUMBER,AMOUNT_ONE)); + + assertEquals(NOT_EXISTING_ACCOUNT_NUMBER, actualException.getAccountNumber()); + } + + @Test + public void getAccount_happyFlow(){ + Mockito.when(bank.getAccounts()).thenReturn(Arrays.asList(NO_AMOUNT_ACCOUNT, AMOUNT_ACCOUNT)); + + Account actualAccount = bankService.getAccount(AMOUNT_ACCOUNT_NUMBER); + + assertEquals(AMOUNT_ACCOUNT_NUMBER, actualAccount.getAccountNumber()); + assertEquals(AMOUNT_ONE, actualAccount.getMoney()); + } + + @Test + public void getAccount_accountDoesNotExist_throwsException(){ + Mockito.when(bank.getAccounts()).thenReturn(Arrays.asList(NO_AMOUNT_ACCOUNT, AMOUNT_ACCOUNT)); + + + AccountNotFoundException actualException = assertThrows(AccountNotFoundException.class, + () -> bankService.getAccount(NOT_EXISTING_ACCOUNT_NUMBER)); + + assertEquals(NOT_EXISTING_ACCOUNT_NUMBER, actualException.getAccountNumber()); + } + + @Test + public void registerAccount_happyFlow(){ + List accounts = new ArrayList(Arrays.asList(NO_AMOUNT_ACCOUNT, AMOUNT_ACCOUNT)); + + Mockito.when(bank.getAccounts()).thenReturn(accounts); + + bankService.registerAccount(NOT_EXISTING_ACCOUNT_NUMBER, AMOUNT_ZERO); + + Mockito.verify(bank).addAccount(accountCaptor.capture()); + + Account capturedAccount = accountCaptor.getValue(); + assertEquals(NOT_EXISTING_ACCOUNT_NUMBER, capturedAccount.getAccountNumber()); + assertEquals(AMOUNT_ZERO, capturedAccount.getMoney()); + } + + @Test + public void registerAccount_accountAlreadyExist_throwException(){ + List accounts = new ArrayList(Arrays.asList(NO_AMOUNT_ACCOUNT, AMOUNT_ACCOUNT)); + + Mockito.when(bank.getAccounts()).thenReturn(accounts); + + AccountExistsException actualException = assertThrows(AccountExistsException.class, + () -> bankService.registerAccount(NO_AMOUNT_ACCOUNT_NUMBER, AMOUNT_ZERO)); + + assertEquals(NO_AMOUNT_ACCOUNT_NUMBER, actualException.getAccountNumber()); + } + + @Test + public void registerAccount_negativeAmountNewAccount_throwsException(){ + List accounts = new ArrayList(Arrays.asList(NO_AMOUNT_ACCOUNT, AMOUNT_ACCOUNT)); + BigDecimal negativeAmount = BigDecimal.valueOf(-1); + + Mockito.when(bank.getAccounts()).thenReturn(accounts); + + IllegalAccountAmountException actualException = assertThrows(IllegalAccountAmountException.class, + () -> bankService.registerAccount(NOT_EXISTING_ACCOUNT_NUMBER, negativeAmount)); + + assertEquals(negativeAmount, actualException.getIllegalAmount()); + } + +} diff --git a/src/main/java/ch/engenius/test/bank/BankTest.java b/src/main/java/ch/engenius/test/bank/BankTest.java new file mode 100644 index 0000000..c9b9614 --- /dev/null +++ b/src/main/java/ch/engenius/test/bank/BankTest.java @@ -0,0 +1,30 @@ +package ch.engenius.test.bank; + +import ch.engenius.bank.model.Account; +import ch.engenius.bank.model.Bank; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@ExtendWith(MockitoExtension.class) +public class BankTest { + + private Bank bank; + + @BeforeEach + public void setUp() { + this.bank = new Bank(); + } + + @Test + public void addAccount_happyFlow() { + Account account = new Account(); + + bank.addAccount(account); + + assertEquals(1, bank.getAccounts().size()); + } +}