diff --git a/pom.xml b/pom.xml index 3994d594..10c9147b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,6 +5,18 @@ com.abc bank 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 11 + 11 + + + + jar bank @@ -20,5 +32,12 @@ 4.11 test + + + org.mockito + mockito-core + 4.7.0 + test + diff --git a/src/main/java/com/abc/Account.java b/src/main/java/com/abc/Account.java deleted file mode 100644 index 099691e0..00000000 --- a/src/main/java/com/abc/Account.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.abc; - -import java.util.ArrayList; -import java.util.List; - -public class Account { - - public static final int CHECKING = 0; - public static final int SAVINGS = 1; - public static final int MAXI_SAVINGS = 2; - - private final int accountType; - public List transactions; - - public Account(int accountType) { - this.accountType = accountType; - this.transactions = new ArrayList(); - } - - public void deposit(double amount) { - if (amount <= 0) { - throw new IllegalArgumentException("amount must be greater than zero"); - } else { - transactions.add(new Transaction(amount)); - } - } - -public void withdraw(double amount) { - if (amount <= 0) { - throw new IllegalArgumentException("amount must be greater than zero"); - } else { - transactions.add(new Transaction(-amount)); - } -} - - public double interestEarned() { - double amount = sumTransactions(); - switch(accountType){ - case SAVINGS: - if (amount <= 1000) - return amount * 0.001; - else - return 1 + (amount-1000) * 0.002; -// case SUPER_SAVINGS: -// if (amount <= 4000) -// return 20; - case MAXI_SAVINGS: - if (amount <= 1000) - return amount * 0.02; - if (amount <= 2000) - return 20 + (amount-1000) * 0.05; - return 70 + (amount-2000) * 0.1; - default: - return amount * 0.001; - } - } - - public double sumTransactions() { - return checkIfTransactionsExist(true); - } - - private double checkIfTransactionsExist(boolean checkAll) { - double amount = 0.0; - for (Transaction t: transactions) - amount += t.amount; - return amount; - } - - public int getAccountType() { - return accountType; - } - -} diff --git a/src/main/java/com/abc/Bank.java b/src/main/java/com/abc/Bank.java deleted file mode 100644 index 5dd535bd..00000000 --- a/src/main/java/com/abc/Bank.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.abc; - -import java.util.ArrayList; -import java.util.List; - -public class Bank { - private List customers; - - public Bank() { - customers = new ArrayList(); - } - - public void addCustomer(Customer customer) { - customers.add(customer); - } - - public String customerSummary() { - String summary = "Customer Summary"; - for (Customer c : customers) - summary += "\n - " + c.getName() + " (" + format(c.getNumberOfAccounts(), "account") + ")"; - return summary; - } - - //Make sure correct plural of word is created based on the number passed in: - //If number passed in is 1 just return the word otherwise add an 's' at the end - private String format(int number, String word) { - return number + " " + (number == 1 ? word : word + "s"); - } - - public double totalInterestPaid() { - double total = 0; - for(Customer c: customers) - total += c.totalInterestEarned(); - return total; - } - - public String getFirstCustomer() { - try { - customers = null; - return customers.get(0).getName(); - } catch (Exception e){ - e.printStackTrace(); - return "Error"; - } - } -} diff --git a/src/main/java/com/abc/Customer.java b/src/main/java/com/abc/Customer.java deleted file mode 100644 index 31571685..00000000 --- a/src/main/java/com/abc/Customer.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.abc; - -import java.util.ArrayList; -import java.util.List; - -import static java.lang.Math.abs; - -public class Customer { - private String name; - private List accounts; - - public Customer(String name) { - this.name = name; - this.accounts = new ArrayList(); - } - - public String getName() { - return name; - } - - public Customer openAccount(Account account) { - accounts.add(account); - return this; - } - - public int getNumberOfAccounts() { - return accounts.size(); - } - - public double totalInterestEarned() { - double total = 0; - for (Account a : accounts) - total += a.interestEarned(); - return total; - } - - public String getStatement() { - String statement = null; - statement = "Statement for " + name + "\n"; - double total = 0.0; - for (Account a : accounts) { - statement += "\n" + statementForAccount(a) + "\n"; - total += a.sumTransactions(); - } - statement += "\nTotal In All Accounts " + toDollars(total); - return statement; - } - - private String statementForAccount(Account a) { - String s = ""; - - //Translate to pretty account type - switch(a.getAccountType()){ - case Account.CHECKING: - s += "Checking Account\n"; - break; - case Account.SAVINGS: - s += "Savings Account\n"; - break; - case Account.MAXI_SAVINGS: - s += "Maxi Savings Account\n"; - break; - } - - //Now total up all the transactions - double total = 0.0; - for (Transaction t : a.transactions) { - s += " " + (t.amount < 0 ? "withdrawal" : "deposit") + " " + toDollars(t.amount) + "\n"; - total += t.amount; - } - s += "Total " + toDollars(total); - return s; - } - - private String toDollars(double d){ - return String.format("$%,.2f", abs(d)); - } -} diff --git a/src/main/java/com/abc/Transaction.java b/src/main/java/com/abc/Transaction.java deleted file mode 100644 index c1f7c67e..00000000 --- a/src/main/java/com/abc/Transaction.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.abc; - -import java.util.Calendar; -import java.util.Date; - -public class Transaction { - public final double amount; - - private Date transactionDate; - - public Transaction(double amount) { - this.amount = amount; - this.transactionDate = DateProvider.getInstance().now(); - } - -} diff --git a/src/main/java/com/abc/account/Account.java b/src/main/java/com/abc/account/Account.java new file mode 100644 index 00000000..98aaabc6 --- /dev/null +++ b/src/main/java/com/abc/account/Account.java @@ -0,0 +1,85 @@ +package com.abc.account; + +import com.abc.customer.Customer; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public abstract class Account { + + private final Customer customer; + private final AccountType accountType; + private final List transactions; + private double balance; + + protected Account(Customer customer, AccountType accountType) { + this.customer = customer; + this.accountType = accountType; + this.transactions = new ArrayList<>(); + } + + public final void deposit(double amount) { + if (amount <= 0) { + throw new IllegalArgumentException("Amount must be greater than zero."); + } + transactions.add(new Transaction(Transaction.TransactionType.DEPOSIT, amount)); + balance += amount; + } + + public final void withdraw(double amount) { + if (amount <= 0) { + throw new IllegalArgumentException("Amount must be greater than zero."); + } + if (balance < amount) { + throw new IllegalArgumentException("Insufficient founds."); + } + transactions.add(new Transaction(Transaction.TransactionType.WITHDREW, amount)); + balance -= amount; + } + + public void transfer(double amount, Account targetAccount) { + if (targetAccount == this) { + throw new IllegalArgumentException("Target account must be a different account."); + } + if (targetAccount == null) { + throw new IllegalArgumentException("Target account cannot be null."); + } + withdraw(amount); + targetAccount.deposit(amount); + } + + // Currently it's the same as the account balance, but I choose not to remove it. + // Later it could be easily extended with a parameter (eg. time interval) + public double sumTransactions() { + double amount = 0.0; + for (Transaction t : transactions) + amount += t.getAmount(); + return amount; + } + + public Transaction getLastTransaction() { + if (transactions.isEmpty()) { + return null; + } + return transactions.get(transactions.size() - 1); + } + + public abstract double calcInterestEarned(); + + public double getBalance() { + return balance; + } + + public Customer getCustomer() { + return customer; + } + + public AccountType getAccountType() { + return accountType; + } + + public List getTransactions() { + return Collections.unmodifiableList(transactions); + } +} diff --git a/src/main/java/com/abc/account/AccountFactory.java b/src/main/java/com/abc/account/AccountFactory.java new file mode 100644 index 00000000..4ce5f975 --- /dev/null +++ b/src/main/java/com/abc/account/AccountFactory.java @@ -0,0 +1,21 @@ +package com.abc.account; + +import com.abc.customer.Customer; + +public class AccountFactory { + + private AccountFactory() { + } + + public static Account create(Customer customer, AccountType accountType) { + switch (accountType) { + case CHECKING: + return new CheckingAccount(customer, accountType); + case SAVINGS: + return new SavingsAccount(customer, accountType); + case MAXI_SAVINGS: + return new MaxiSavingsAccount(customer, accountType); + } + throw new IllegalArgumentException("Invalid account type."); + } +} diff --git a/src/main/java/com/abc/account/AccountType.java b/src/main/java/com/abc/account/AccountType.java new file mode 100644 index 00000000..190fda10 --- /dev/null +++ b/src/main/java/com/abc/account/AccountType.java @@ -0,0 +1,17 @@ +package com.abc.account; + +public enum AccountType { + CHECKING("Checking Account"), + SAVINGS("Savings Account"), + MAXI_SAVINGS("Maxi Savings Account"); + + private final String prettyName; + + AccountType(String prettyName) { + this.prettyName = prettyName; + } + + public String getPrettyName() { + return prettyName; + } +} diff --git a/src/main/java/com/abc/account/CheckingAccount.java b/src/main/java/com/abc/account/CheckingAccount.java new file mode 100644 index 00000000..1fe8fc5f --- /dev/null +++ b/src/main/java/com/abc/account/CheckingAccount.java @@ -0,0 +1,16 @@ +package com.abc.account; + +import com.abc.customer.Customer; + +public class CheckingAccount extends Account { + + CheckingAccount(Customer customer, AccountType accountType) { + super(customer, accountType); + } + + @Override + public double calcInterestEarned() { + double amount = getBalance(); + return amount * 0.001; + } +} diff --git a/src/main/java/com/abc/account/MaxiSavingsAccount.java b/src/main/java/com/abc/account/MaxiSavingsAccount.java new file mode 100644 index 00000000..acf2784c --- /dev/null +++ b/src/main/java/com/abc/account/MaxiSavingsAccount.java @@ -0,0 +1,34 @@ +package com.abc.account; + +import com.abc.customer.Customer; +import com.abc.util.DateProvider; + +import java.util.Date; +import java.util.concurrent.TimeUnit; + +public class MaxiSavingsAccount extends Account { + + MaxiSavingsAccount(Customer customer, AccountType accountType) { + super(customer, accountType); + } + + @Override + public double calcInterestEarned() { + double amount = getBalance(); + if (calcDayDiff() > 10) { + return amount * 0.05; + } else { + return amount * 0.001; + } + } + + private long calcDayDiff() { + Transaction transaction = getLastTransaction(); + if (transaction == null) { + return Long.MAX_VALUE; + } + Date today = DateProvider.getInstance().now(); + long diffInMillis = Math.abs(today.getTime() - transaction.getTransactionDate().getTime()); + return TimeUnit.DAYS.convert(diffInMillis, TimeUnit.MILLISECONDS); + } +} diff --git a/src/main/java/com/abc/account/SavingsAccount.java b/src/main/java/com/abc/account/SavingsAccount.java new file mode 100644 index 00000000..d260fad8 --- /dev/null +++ b/src/main/java/com/abc/account/SavingsAccount.java @@ -0,0 +1,19 @@ +package com.abc.account; + +import com.abc.customer.Customer; + +public class SavingsAccount extends Account { + + SavingsAccount(Customer customer, AccountType accountType) { + super(customer, accountType); + } + + @Override + public double calcInterestEarned() { + double amount = getBalance(); + if (amount <= 1000) + return amount * 0.001; + else + return 1 + (amount - 1000) * 0.002; + } +} diff --git a/src/main/java/com/abc/account/Transaction.java b/src/main/java/com/abc/account/Transaction.java new file mode 100644 index 00000000..06311db8 --- /dev/null +++ b/src/main/java/com/abc/account/Transaction.java @@ -0,0 +1,32 @@ +package com.abc.account; + +import com.abc.util.DateProvider; + +import java.util.Date; + +public class Transaction { + private final double amount; + private final Date transactionDate; + private final TransactionType transactionType; + + public enum TransactionType { + WITHDREW, DEPOSIT; + } + + public Transaction(TransactionType transactionType, double amount) { + this.transactionType = transactionType; + this.amount = amount; + this.transactionDate = DateProvider.getInstance().now(); + } + + public double getAmount() { + if (transactionType == TransactionType.WITHDREW) { + return -amount; + } + return amount; + } + + public Date getTransactionDate() { + return transactionDate; + } +} diff --git a/src/main/java/com/abc/bank/Bank.java b/src/main/java/com/abc/bank/Bank.java new file mode 100644 index 00000000..6e27705c --- /dev/null +++ b/src/main/java/com/abc/bank/Bank.java @@ -0,0 +1,58 @@ +package com.abc.bank; + +import com.abc.account.Account; +import com.abc.account.AccountFactory; +import com.abc.account.AccountType; +import com.abc.customer.Customer; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Bank { + private final List customers; + + public Bank() { + customers = new ArrayList<>(); + } + + public void addCustomer(Customer customer) { + if (customer != null && !customers.contains(customer)) { + customers.add(customer); + customer.setBank(this); + } + } + + public String createCustomerSummary() { + StringBuilder summary = new StringBuilder("Customer Summary"); + for (Customer customer : customers) { + int numberOfAccounts = customer.getNumberOfAccounts(); + String pluralFormat = pluralFormat(numberOfAccounts, " account"); + String customerSummary = String.format("\n - %s (%s%s)", + customer.getName(), + numberOfAccounts, + pluralFormat); + summary.append(customerSummary); + } + return summary.toString(); + } + + private String pluralFormat(int number, String word) { + return number == 1 ? word : word + "s"; + } + + public double totalInterestPaid() { + double total = 0; + for (Customer customer : customers) + total += customer.totalInterestEarned(); + return total; + } + + public Account createAccount(Customer customer, AccountType accountType) { + return AccountFactory.create(customer, accountType); + } + + public List getCustomers() { + return Collections.unmodifiableList(customers); + } +} diff --git a/src/main/java/com/abc/customer/Customer.java b/src/main/java/com/abc/customer/Customer.java new file mode 100644 index 00000000..7b2a04f5 --- /dev/null +++ b/src/main/java/com/abc/customer/Customer.java @@ -0,0 +1,60 @@ +package com.abc.customer; + +import com.abc.bank.Bank; +import com.abc.account.Account; +import com.abc.account.AccountType; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Customer { + private final String name; + private final List accounts; + private Bank bank; + + public Customer(String name) { + this.name = name; + this.accounts = new ArrayList<>(); + } + + public Account openAccount(AccountType accountType) { + if (bank == null) { + throw new IllegalArgumentException("Customer should be assigned to a bank first."); + } + Account account = bank.createAccount(this, accountType); + accounts.add(account); + return account; + } + + public int getNumberOfAccounts() { + return accounts.size(); + } + + public double totalInterestEarned() { + double total = 0.0; + for (Account a : accounts) + total += a.calcInterestEarned(); + return total; + } + + public String getStatement() { + return CustomerStatement.create(this); + } + + public String getName() { + return name; + } + + public List getAccounts() { + return Collections.unmodifiableList(accounts); + } + + public Bank getBank() { + return bank; + } + + public void setBank(Bank bank) { + this.bank = bank; + } +} diff --git a/src/main/java/com/abc/customer/CustomerStatement.java b/src/main/java/com/abc/customer/CustomerStatement.java new file mode 100644 index 00000000..73eecb72 --- /dev/null +++ b/src/main/java/com/abc/customer/CustomerStatement.java @@ -0,0 +1,58 @@ +package com.abc.customer; + +import com.abc.account.Transaction; +import com.abc.account.Account; + +import static java.lang.Math.abs; + +public final class CustomerStatement { + + private CustomerStatement() { + } + + private static final String LINE_BREAK = "\n"; + + public static String create(Customer customer) { + StringBuilder statement = new StringBuilder("Statement for "); + statement.append(customer.getName()); + statement.append(LINE_BREAK); + for (Account account : customer.getAccounts()) { + statement.append(LINE_BREAK); + statement.append(statementForAccount(account)); + statement.append(LINE_BREAK); + } + statement.append(LINE_BREAK); + statement.append("Total In All Accounts "); + statement.append(toDollars(sumAllTransactions(customer))); + return statement.toString(); + } + + private static String statementForAccount(Account account) { + StringBuilder sb = new StringBuilder(account.getAccountType().getPrettyName()); + sb.append(LINE_BREAK); + for (Transaction t : account.getTransactions()) { + if (t.getAmount() < 0) { + sb.append(" withdrawal "); + } else { + sb.append(" deposit "); + } + sb.append(toDollars(t.getAmount())); + sb.append(LINE_BREAK); + } + sb.append("Total "); + sb.append(toDollars(account.sumTransactions())); + return sb.toString(); + } + + private static double sumAllTransactions(Customer customer) { + double total = 0.0; + for (Account account : customer.getAccounts()) { + total += account.sumTransactions(); + } + return total; + } + + private static String toDollars(double d) { + return String.format("$%,.2f", abs(d)); + } +} diff --git a/src/main/java/com/abc/DateProvider.java b/src/main/java/com/abc/util/DateProvider.java similarity index 86% rename from src/main/java/com/abc/DateProvider.java rename to src/main/java/com/abc/util/DateProvider.java index 035ee90b..f76a96c5 100644 --- a/src/main/java/com/abc/DateProvider.java +++ b/src/main/java/com/abc/util/DateProvider.java @@ -1,4 +1,4 @@ -package com.abc; +package com.abc.util; import java.util.Calendar; import java.util.Date; @@ -6,6 +6,9 @@ public class DateProvider { private static DateProvider instance = null; + private DateProvider() { + } + public static DateProvider getInstance() { if (instance == null) instance = new DateProvider(); diff --git a/src/test/java/com/abc/BankTest.java b/src/test/java/com/abc/BankTest.java deleted file mode 100644 index f8a82896..00000000 --- a/src/test/java/com/abc/BankTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.abc; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class BankTest { - private static final double DOUBLE_DELTA = 1e-15; - - @Test - public void customerSummary() { - Bank bank = new Bank(); - Customer john = new Customer("John"); - john.openAccount(new Account(Account.CHECKING)); - bank.addCustomer(john); - - assertEquals("Customer Summary\n - John (1 account)", bank.customerSummary()); - } - - @Test - public void checkingAccount() { - Bank bank = new Bank(); - Account checkingAccount = new Account(Account.CHECKING); - Customer bill = new Customer("Bill").openAccount(checkingAccount); - bank.addCustomer(bill); - - checkingAccount.deposit(100.0); - - assertEquals(0.1, bank.totalInterestPaid(), DOUBLE_DELTA); - } - - @Test - public void savings_account() { - Bank bank = new Bank(); - Account checkingAccount = new Account(Account.SAVINGS); - bank.addCustomer(new Customer("Bill").openAccount(checkingAccount)); - - checkingAccount.deposit(1500.0); - - assertEquals(2.0, bank.totalInterestPaid(), DOUBLE_DELTA); - } - - @Test - public void maxi_savings_account() { - Bank bank = new Bank(); - Account checkingAccount = new Account(Account.MAXI_SAVINGS); - bank.addCustomer(new Customer("Bill").openAccount(checkingAccount)); - - checkingAccount.deposit(3000.0); - - assertEquals(170.0, bank.totalInterestPaid(), DOUBLE_DELTA); - } - -} diff --git a/src/test/java/com/abc/CustomerTest.java b/src/test/java/com/abc/CustomerTest.java deleted file mode 100644 index b8df9498..00000000 --- a/src/test/java/com/abc/CustomerTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.abc; - -import org.junit.Ignore; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class CustomerTest { - - @Test //Test customer statement generation - public void testApp(){ - - Account checkingAccount = new Account(Account.CHECKING); - Account savingsAccount = new Account(Account.SAVINGS); - - Customer henry = new Customer("Henry").openAccount(checkingAccount).openAccount(savingsAccount); - - checkingAccount.deposit(100.0); - savingsAccount.deposit(4000.0); - savingsAccount.withdraw(200.0); - - assertEquals("Statement for Henry\n" + - "\n" + - "Checking Account\n" + - " deposit $100.00\n" + - "Total $100.00\n" + - "\n" + - "Savings Account\n" + - " deposit $4,000.00\n" + - " withdrawal $200.00\n" + - "Total $3,800.00\n" + - "\n" + - "Total In All Accounts $3,900.00", henry.getStatement()); - } - - @Test - public void testOneAccount(){ - Customer oscar = new Customer("Oscar").openAccount(new Account(Account.SAVINGS)); - assertEquals(1, oscar.getNumberOfAccounts()); - } - - @Test - public void testTwoAccount(){ - Customer oscar = new Customer("Oscar") - .openAccount(new Account(Account.SAVINGS)); - oscar.openAccount(new Account(Account.CHECKING)); - assertEquals(2, oscar.getNumberOfAccounts()); - } - - @Ignore - public void testThreeAcounts() { - Customer oscar = new Customer("Oscar") - .openAccount(new Account(Account.SAVINGS)); - oscar.openAccount(new Account(Account.CHECKING)); - assertEquals(3, oscar.getNumberOfAccounts()); - } -} diff --git a/src/test/java/com/abc/TransactionTest.java b/src/test/java/com/abc/TransactionTest.java deleted file mode 100644 index 28983234..00000000 --- a/src/test/java/com/abc/TransactionTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.abc; - -import org.junit.Test; - -import static org.junit.Assert.assertTrue; - -public class TransactionTest { - @Test - public void transaction() { - Transaction t = new Transaction(5); - assertTrue(t instanceof Transaction); - } -} diff --git a/src/test/java/com/abc/account/AccountTest.java b/src/test/java/com/abc/account/AccountTest.java new file mode 100644 index 00000000..30f2da05 --- /dev/null +++ b/src/test/java/com/abc/account/AccountTest.java @@ -0,0 +1,81 @@ +package com.abc.account; + +import com.abc.customer.Customer; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class AccountTest { + + private final String TEST_CUSTOMER_NAME = "Josh"; + private final double DELTA = 1e-15; + + @Test + public void testDeposit() { + Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS); + account.deposit(150.0); + account.deposit(350.0); + account.deposit(100.0); + assertEquals(600.0, account.getBalance(), DELTA); + } + + @Test(expected = IllegalArgumentException.class) + public void testDepositWithZeroAmount() { + Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS); + account.deposit(0.0); + } + + @Test + public void testWithdraw() { + Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS); + account.deposit(600.0); + account.withdraw(100.0); + assertEquals(500.0, account.getBalance(), DELTA); + } + + @Test(expected = IllegalArgumentException.class) + public void testWithdrawWithZeroAmount() { + Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS); + account.deposit(100.0); + account.withdraw(0.0); + } + + @Test(expected = IllegalArgumentException.class) + public void testWithdrawIfAmountGreaterThanBalance() { + Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS); + account.deposit(100.0); + account.withdraw(2000.0); + } + + @Test + public void testSumTransactions() { + Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS); + account.deposit(100.0); + account.withdraw(20.0); + account.deposit(200.0); + account.withdraw(100.0); + assertEquals(180.0, account.sumTransactions(), DELTA); + } + + @Test(expected = IllegalArgumentException.class) + public void testTransferWhenTargetAccountIsNull() { + Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS); + account.transfer(100.0, null); + } + + @Test(expected = IllegalArgumentException.class) + public void testTransferWhenTargetAccountIsTheSameAccount() { + Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS); + account.transfer(100.0, account); + } + + @Test + public void testTransfer() { + Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS); + Account targetAccount = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.CHECKING); + account.deposit(100.0); + account.transfer(30.0, targetAccount); + assertEquals(70.0, account.getBalance(), DELTA); + assertEquals(30.0, targetAccount.getBalance(), DELTA); + } +} \ No newline at end of file diff --git a/src/test/java/com/abc/account/CheckingAccountTest.java b/src/test/java/com/abc/account/CheckingAccountTest.java new file mode 100644 index 00000000..014f5ddf --- /dev/null +++ b/src/test/java/com/abc/account/CheckingAccountTest.java @@ -0,0 +1,19 @@ +package com.abc.account; + +import com.abc.customer.Customer; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class CheckingAccountTest { + + private final String TEST_CUSTOMER_NAME = "Josh"; + private final double DELTA = 1e-15; + + @Test + public void testCalcInterestEarned() { + Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.CHECKING); + account.deposit(1900.0); + assertEquals(1.9, account.calcInterestEarned(), DELTA); + } +} \ No newline at end of file diff --git a/src/test/java/com/abc/account/MaxiSavingsAccountTest.java b/src/test/java/com/abc/account/MaxiSavingsAccountTest.java new file mode 100644 index 00000000..54c1f457 --- /dev/null +++ b/src/test/java/com/abc/account/MaxiSavingsAccountTest.java @@ -0,0 +1,55 @@ +package com.abc.account; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class MaxiSavingsAccountTest { + + @Mock + private Transaction mockTransaction; + + @Mock + private MaxiSavingsAccount mockAccount; + + private final double DELTA = 1e-15; + + @Test + public void testCalcInterestEarnedWhenLastTransactionInLessThan10Days() { + when(mockAccount.getLastTransaction()).thenReturn(mockTransaction); + when(mockAccount.getBalance()).thenReturn(900.0); + when(mockTransaction.getTransactionDate()).thenReturn( + new Date()); + when(mockAccount.calcInterestEarned()).thenCallRealMethod(); + assertEquals(0.9, mockAccount.calcInterestEarned(), DELTA); + } + + @Test + public void testCalcInterestEarnedWhenLastTransactionInMoreThan10Days() throws ParseException { + when(mockAccount.getLastTransaction()).thenReturn(mockTransaction); + when(mockAccount.getBalance()).thenReturn(900.0); + when(mockTransaction.getTransactionDate()).thenReturn( + new SimpleDateFormat("MM/dd/yyyy").parse("08/16/2022")); + when(mockAccount.calcInterestEarned()).thenCallRealMethod(); + assertEquals(45, mockAccount.calcInterestEarned(), DELTA); + } + + @Test + public void testCalcInterestEarnedWithNoTransactions() { + when(mockAccount.getLastTransaction()).thenReturn(null); + when(mockAccount.getBalance()).thenCallRealMethod(); + when(mockAccount.calcInterestEarned()).thenCallRealMethod(); + assertEquals(0, mockAccount.calcInterestEarned(), DELTA); + } + +} \ No newline at end of file diff --git a/src/test/java/com/abc/account/SavingsAccountTest.java b/src/test/java/com/abc/account/SavingsAccountTest.java new file mode 100644 index 00000000..dc506bec --- /dev/null +++ b/src/test/java/com/abc/account/SavingsAccountTest.java @@ -0,0 +1,26 @@ +package com.abc.account; + +import com.abc.customer.Customer; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class SavingsAccountTest { + + private final String TEST_CUSTOMER_NAME = "Josh"; + private final double DELTA = 1e-15; + + @Test + public void testCalcInterestEarnedWithAmountLessThan1000() { + Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS); + account.deposit(900.0); + assertEquals(0.9, account.calcInterestEarned(), DELTA); + } + + @Test + public void testCalcInterestEarnedWithAmountGreaterThan1000() { + Account account = AccountFactory.create(new Customer(TEST_CUSTOMER_NAME), AccountType.SAVINGS); + account.deposit(1900.0); + assertEquals(2.8, account.calcInterestEarned(), DELTA); + } +} \ No newline at end of file diff --git a/src/test/java/com/abc/bank/BankTest.java b/src/test/java/com/abc/bank/BankTest.java new file mode 100644 index 00000000..39b05c1a --- /dev/null +++ b/src/test/java/com/abc/bank/BankTest.java @@ -0,0 +1,70 @@ +package com.abc.bank; + +import com.abc.account.AccountType; +import com.abc.customer.Customer; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class BankTest { + + private final double DELTA = 1e-15; + + @Mock + private Customer mockCustomer1; + @Mock + private Customer mockCustomer2; + @Mock + private Customer mockCustomer3; + + @Test + public void testCustomerSummary() { + when(mockCustomer1.getName()).thenReturn("John"); + when(mockCustomer1.getNumberOfAccounts()).thenReturn(1); + when(mockCustomer2.getName()).thenReturn("James"); + when(mockCustomer2.getNumberOfAccounts()).thenReturn(2); + + Bank bank = new Bank(); + bank.addCustomer(mockCustomer1); + bank.addCustomer(mockCustomer2); + + assertEquals( + "Customer Summary\n - John (1 account)\n - James (2 accounts)", + bank.createCustomerSummary()); + } + + @Test + public void testAddCustomer() { + Bank bank = new Bank(); + bank.addCustomer(mockCustomer1); + bank.addCustomer(mockCustomer2); + bank.addCustomer(mockCustomer3); + bank.addCustomer(mockCustomer1); + bank.addCustomer(null); + assertEquals(3, bank.getCustomers().size()); + } + + @Test + public void testTotalInterestPaid() { + when(mockCustomer1.totalInterestEarned()).thenReturn(1.0); + when(mockCustomer2.totalInterestEarned()).thenReturn(2.0); + when(mockCustomer3.totalInterestEarned()).thenReturn(3.0); + Bank bank = new Bank(); + bank.addCustomer(mockCustomer1); + bank.addCustomer(mockCustomer2); + bank.addCustomer(mockCustomer3); + assertEquals(6.0, bank.totalInterestPaid(), DELTA); + } + + @Test + public void testCreateAccount() { + Bank bank = new Bank(); + assertNotNull(bank.createAccount(mockCustomer1, AccountType.CHECKING)); + } +} diff --git a/src/test/java/com/abc/customer/CustomerStatementTest.java b/src/test/java/com/abc/customer/CustomerStatementTest.java new file mode 100644 index 00000000..ec04380a --- /dev/null +++ b/src/test/java/com/abc/customer/CustomerStatementTest.java @@ -0,0 +1,58 @@ +package com.abc.customer; + +import com.abc.account.*; +import com.abc.bank.Bank; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import java.util.ArrayList; +import java.util.Arrays; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class CustomerStatementTest { + + @Mock + private Customer mockCustomer; + + @Mock + private SavingsAccount mockSavingsAccount; + + @Mock + private CheckingAccount mockCheckingAccount; + + @Test + public void create() { + Transaction transaction1 = new Transaction(Transaction.TransactionType.DEPOSIT, 100.0); + Transaction transaction2 = new Transaction(Transaction.TransactionType.DEPOSIT, 4000.0); + Transaction transaction3 = new Transaction(Transaction.TransactionType.WITHDREW, 200.0); + + when(mockCustomer.getName()).thenReturn("Henry"); + when(mockCustomer.getAccounts()).thenReturn(new ArrayList<>(Arrays.asList(mockCheckingAccount, mockSavingsAccount))); + when(mockCheckingAccount.getTransactions()).thenReturn(new ArrayList<>(Arrays.asList(transaction1))); + when(mockSavingsAccount.getTransactions()).thenReturn(new ArrayList<>(Arrays.asList(transaction2, transaction3))); + when(mockCheckingAccount.getAccountType()).thenReturn(AccountType.CHECKING); + when(mockSavingsAccount.getAccountType()).thenReturn(AccountType.SAVINGS); + when(mockCheckingAccount.sumTransactions()).thenReturn(100.0); + when(mockSavingsAccount.sumTransactions()).thenReturn(3800.0); + when(mockCustomer.getStatement()).thenCallRealMethod(); + + assertEquals("Statement for Henry\n" + + "\n" + + "Checking Account\n" + + " deposit $100.00\n" + + "Total $100.00\n" + + "\n" + + "Savings Account\n" + + " deposit $4,000.00\n" + + " withdrawal $200.00\n" + + "Total $3,800.00\n" + + "\n" + + "Total In All Accounts $3,900.00", mockCustomer.getStatement()); + } + +} \ No newline at end of file diff --git a/src/test/java/com/abc/customer/CustomerTest.java b/src/test/java/com/abc/customer/CustomerTest.java new file mode 100644 index 00000000..c41eef4a --- /dev/null +++ b/src/test/java/com/abc/customer/CustomerTest.java @@ -0,0 +1,52 @@ +package com.abc.customer; + +import com.abc.account.AccountFactory; +import com.abc.bank.Bank; +import com.abc.account.AccountType; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class CustomerTest { + + @Mock + private Bank mockBank; + + @Test + public void testGetNumberOfAccountsWith0Accounts() { + Customer oscar = new Customer("Oscar"); + assertEquals(0, oscar.getNumberOfAccounts()); + } + + @Test + public void testGetNumberOfAccountsWith3Accounts() { + Bank bank = new Bank(); + Customer oscar = new Customer("Oscar"); + bank.addCustomer(oscar); + for (int i = 0; i < 3; i++) { + oscar.openAccount(AccountType.SAVINGS); + } + assertEquals(3, oscar.getNumberOfAccounts()); + } + + @Test(expected = IllegalArgumentException.class) + public void testOpenAccountWhenBankIsNull() { + Customer customer = new Customer("Anna"); + customer.openAccount(AccountType.CHECKING); + } + + @Test + public void testOpenAccount() { + Customer customer = new Customer("Anna"); + customer.setBank(mockBank); + when(mockBank.createAccount(customer, AccountType.CHECKING)) + .thenReturn(AccountFactory.create(customer,AccountType.CHECKING)); + assertNotNull(customer.openAccount(AccountType.CHECKING)); + } +}