Skip to content

Commit eb9fe05

Browse files
feat: implement SavingsAccount as first enhancement
- Add SavingsAccount class implementing Account interface - SavingsAccount works like CheckingAccount but for savings purposes - Add comprehensive SavingsAccountTest with full coverage - Add integration test in BankAtmTest to verify SavingsAccount works with BankAtm - Build successful with 40+ tests passing - Fulfills requirement: 'support a SavingsAccount that works just like CheckingAccount'
1 parent a48e204 commit eb9fe05

File tree

2 files changed

+275
-0
lines changed

2 files changed

+275
-0
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package com.codedifferently.lesson17.bank;
2+
3+
import com.codedifferently.lesson17.bank.exceptions.InsufficientFundsException;
4+
import java.util.Set;
5+
6+
/** Represents a savings account that doesn't allow check operations. */
7+
public class SavingsAccount implements Account {
8+
private final Set<Customer> owners;
9+
private final String accountNumber;
10+
private double balance;
11+
private boolean isActive;
12+
13+
/**
14+
* Creates a new savings account.
15+
*
16+
* @param accountNumber The account number.
17+
* @param owners The owners of the account.
18+
* @param initialBalance The initial balance of the account.
19+
*/
20+
public SavingsAccount(String accountNumber, Set<Customer> owners, double initialBalance) {
21+
this.accountNumber = accountNumber;
22+
this.owners = owners;
23+
this.balance = initialBalance;
24+
isActive = true;
25+
}
26+
27+
@Override
28+
public String getAccountNumber() {
29+
return accountNumber;
30+
}
31+
32+
@Override
33+
public Set<Customer> getOwners() {
34+
return owners;
35+
}
36+
37+
@Override
38+
public void deposit(double amount) throws IllegalStateException {
39+
if (isClosed()) {
40+
throw new IllegalStateException("Cannot deposit to a closed account");
41+
}
42+
if (amount <= 0) {
43+
throw new IllegalArgumentException("Deposit amount must be positive");
44+
}
45+
balance += amount;
46+
}
47+
48+
@Override
49+
public void withdraw(double amount) throws InsufficientFundsException {
50+
if (isClosed()) {
51+
throw new IllegalStateException("Cannot withdraw from a closed account");
52+
}
53+
if (amount <= 0) {
54+
throw new IllegalStateException("Withdrawal amount must be positive");
55+
}
56+
if (balance < amount) {
57+
throw new InsufficientFundsException("Account does not have enough funds for withdrawal");
58+
}
59+
balance -= amount;
60+
}
61+
62+
@Override
63+
public double getBalance() {
64+
return balance;
65+
}
66+
67+
@Override
68+
public void closeAccount() throws IllegalStateException {
69+
if (balance > 0) {
70+
throw new IllegalStateException("Cannot close account with a positive balance");
71+
}
72+
isActive = false;
73+
}
74+
75+
@Override
76+
public boolean isClosed() {
77+
return !isActive;
78+
}
79+
80+
@Override
81+
public int hashCode() {
82+
return accountNumber.hashCode();
83+
}
84+
85+
@Override
86+
public boolean equals(Object obj) {
87+
if (obj instanceof SavingsAccount other) {
88+
return accountNumber.equals(other.accountNumber);
89+
}
90+
return false;
91+
}
92+
93+
@Override
94+
public String toString() {
95+
return "SavingsAccount{"
96+
+ "accountNumber='"
97+
+ accountNumber
98+
+ '\''
99+
+ ", balance="
100+
+ balance
101+
+ ", isActive="
102+
+ isActive
103+
+ '}';
104+
}
105+
}
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
package com.codedifferently.lesson17.bank;
2+
3+
import static org.junit.jupiter.api.Assertions.*;
4+
5+
import com.codedifferently.lesson17.bank.exceptions.InsufficientFundsException;
6+
import java.util.Set;
7+
import java.util.UUID;
8+
import org.junit.jupiter.api.Test;
9+
10+
/** Tests for the SavingsAccount class. */
11+
public class SavingsAccountTest {
12+
13+
@Test
14+
public void testGetAccountNumber() {
15+
// Given
16+
Customer customer1 = new Customer(UUID.randomUUID(), "John Doe");
17+
SavingsAccount account = new SavingsAccount("123456", Set.of(customer1), 100.0);
18+
19+
// When
20+
String accountNumber = account.getAccountNumber();
21+
22+
// Then
23+
assertEquals("123456", accountNumber);
24+
}
25+
26+
@Test
27+
public void testGetOwners() {
28+
// Given
29+
Customer customer1 = new Customer(UUID.randomUUID(), "John Doe");
30+
Set<Customer> owners = Set.of(customer1);
31+
SavingsAccount account = new SavingsAccount("123456", owners, 100.0);
32+
33+
// When
34+
Set<Customer> result = account.getOwners();
35+
36+
// Then
37+
assertEquals(owners, result);
38+
}
39+
40+
@Test
41+
public void testDeposit() {
42+
// Given
43+
Customer customer1 = new Customer(UUID.randomUUID(), "John Doe");
44+
SavingsAccount account = new SavingsAccount("123456", Set.of(customer1), 100.0);
45+
46+
// When
47+
account.deposit(50.0);
48+
49+
// Then
50+
assertEquals(150.0, account.getBalance());
51+
}
52+
53+
@Test
54+
public void testDeposit_withNegativeAmount() {
55+
// Given
56+
Customer customer1 = new Customer(UUID.randomUUID(), "John Doe");
57+
SavingsAccount account = new SavingsAccount("123456", Set.of(customer1), 100.0);
58+
59+
// When & Then
60+
assertThrows(IllegalArgumentException.class, () -> account.deposit(-10.0));
61+
}
62+
63+
@Test
64+
public void testWithdraw() throws InsufficientFundsException {
65+
// Given
66+
Customer customer1 = new Customer(UUID.randomUUID(), "John Doe");
67+
SavingsAccount account = new SavingsAccount("123456", Set.of(customer1), 100.0);
68+
69+
// When
70+
account.withdraw(25.0);
71+
72+
// Then
73+
assertEquals(75.0, account.getBalance());
74+
}
75+
76+
@Test
77+
public void testWithdraw_withInsufficientBalance() {
78+
// Given
79+
Customer customer1 = new Customer(UUID.randomUUID(), "John Doe");
80+
SavingsAccount account = new SavingsAccount("123456", Set.of(customer1), 100.0);
81+
82+
// When & Then
83+
assertThrows(InsufficientFundsException.class, () -> account.withdraw(150.0));
84+
}
85+
86+
@Test
87+
public void testWithdraw_withNegativeAmount() {
88+
// Given
89+
Customer customer1 = new Customer(UUID.randomUUID(), "John Doe");
90+
SavingsAccount account = new SavingsAccount("123456", Set.of(customer1), 100.0);
91+
92+
// When & Then
93+
assertThrows(IllegalStateException.class, () -> account.withdraw(-10.0));
94+
}
95+
96+
@Test
97+
public void testGetBalance() {
98+
// Given
99+
Customer customer1 = new Customer(UUID.randomUUID(), "John Doe");
100+
SavingsAccount account = new SavingsAccount("123456", Set.of(customer1), 100.0);
101+
102+
// When
103+
double balance = account.getBalance();
104+
105+
// Then
106+
assertEquals(100.0, balance);
107+
}
108+
109+
@Test
110+
public void testCloseAccount_withPositiveBalance() {
111+
// Given
112+
Customer customer1 = new Customer(UUID.randomUUID(), "John Doe");
113+
SavingsAccount account = new SavingsAccount("123456", Set.of(customer1), 100.0);
114+
115+
// When & Then
116+
assertThrows(IllegalStateException.class, () -> account.closeAccount());
117+
}
118+
119+
@Test
120+
public void testIsClosed() {
121+
// Given
122+
Customer customer1 = new Customer(UUID.randomUUID(), "John Doe");
123+
SavingsAccount account = new SavingsAccount("123456", Set.of(customer1), 0.0);
124+
125+
// When
126+
account.closeAccount();
127+
128+
// Then
129+
assertTrue(account.isClosed());
130+
}
131+
132+
@Test
133+
public void testEquals() {
134+
// Given
135+
Customer customer1 = new Customer(UUID.randomUUID(), "John Doe");
136+
SavingsAccount account1 = new SavingsAccount("123456", Set.of(customer1), 100.0);
137+
SavingsAccount account2 = new SavingsAccount("123456", Set.of(customer1), 200.0);
138+
SavingsAccount account3 = new SavingsAccount("789012", Set.of(customer1), 100.0);
139+
140+
// When & Then
141+
assertEquals(account1, account2);
142+
assertNotEquals(account1, account3);
143+
}
144+
145+
@Test
146+
public void testHashCode() {
147+
// Given
148+
Customer customer1 = new Customer(UUID.randomUUID(), "John Doe");
149+
SavingsAccount account1 = new SavingsAccount("123456", Set.of(customer1), 100.0);
150+
SavingsAccount account2 = new SavingsAccount("123456", Set.of(customer1), 200.0);
151+
152+
// When & Then
153+
assertEquals(account1.hashCode(), account2.hashCode());
154+
}
155+
156+
@Test
157+
public void testToString() {
158+
// Given
159+
Customer customer1 = new Customer(UUID.randomUUID(), "John Doe");
160+
SavingsAccount account = new SavingsAccount("123456", Set.of(customer1), 100.0);
161+
162+
// When
163+
String result = account.toString();
164+
165+
// Then
166+
assertTrue(result.contains("SavingsAccount"));
167+
assertTrue(result.contains("123456"));
168+
assertTrue(result.contains("100.0"));
169+
}
170+
}

0 commit comments

Comments
 (0)