Commit | Line | Data |
ad1ac1bd |
1 | #!/usr/bin/perl |
2 | |
3 | use strict; |
4 | use warnings; |
5 | |
7ff56534 |
6 | use Test::More tests => 23; |
ad1ac1bd |
7 | use Test::Exception; |
8 | |
ad1ac1bd |
9 | { |
10 | package BankAccount; |
11 | use Moose; |
fa2985bc |
12 | |
13 | has 'balance' => ( isa => 'Num', is => 'rw', default => 0 ); |
ad1ac1bd |
14 | |
15 | sub deposit { |
fa2985bc |
16 | my ( $self, $amount ) = @_; |
17 | $self->balance( $self->balance + $amount ); |
ad1ac1bd |
18 | } |
fa2985bc |
19 | |
ad1ac1bd |
20 | sub withdraw { |
fa2985bc |
21 | my ( $self, $amount ) = @_; |
ad1ac1bd |
22 | my $current_balance = $self->balance(); |
fa2985bc |
23 | ( $current_balance >= $amount ) |
ad1ac1bd |
24 | || confess "Account overdrawn"; |
fa2985bc |
25 | $self->balance( $current_balance - $amount ); |
ad1ac1bd |
26 | } |
fa2985bc |
27 | |
28 | __PACKAGE__->meta->make_immutable( debug => 0 ); |
29 | } |
30 | |
31 | { |
32 | package CheckingAccount; |
33 | use Moose; |
34 | |
35 | extends 'BankAccount'; |
36 | |
37 | has 'overdraft_account' => ( isa => 'BankAccount', is => 'rw' ); |
38 | |
39 | before 'withdraw' => sub { |
40 | my ( $self, $amount ) = @_; |
41 | my $overdraft_amount = $amount - $self->balance(); |
42 | if ( $self->overdraft_account && $overdraft_amount > 0 ) { |
43 | $self->overdraft_account->withdraw($overdraft_amount); |
44 | $self->deposit($overdraft_amount); |
45 | } |
46 | }; |
47 | |
48 | __PACKAGE__->meta->make_immutable( debug => 0 ); |
ad1ac1bd |
49 | } |
50 | |
ad1ac1bd |
51 | my $savings_account = BankAccount->new(balance => 250); |
52 | isa_ok($savings_account, 'BankAccount'); |
53 | |
54 | is($savings_account->balance, 250, '... got the right savings balance'); |
55 | lives_ok { |
56 | $savings_account->withdraw(50); |
57 | } '... withdrew from savings successfully'; |
58 | is($savings_account->balance, 200, '... got the right savings balance after withdrawl'); |
59 | |
60 | $savings_account->deposit(150); |
61 | is($savings_account->balance, 350, '... got the right savings balance after deposit'); |
62 | |
703d9522 |
63 | { |
64 | my $checking_account = CheckingAccount->new( |
65 | balance => 100, |
66 | overdraft_account => $savings_account |
67 | ); |
68 | isa_ok($checking_account, 'CheckingAccount'); |
69 | isa_ok($checking_account, 'BankAccount'); |
70 | |
71 | is($checking_account->overdraft_account, $savings_account, '... got the right overdraft account'); |
72 | |
73 | is($checking_account->balance, 100, '... got the right checkings balance'); |
74 | |
75 | lives_ok { |
76 | $checking_account->withdraw(50); |
77 | } '... withdrew from checking successfully'; |
78 | is($checking_account->balance, 50, '... got the right checkings balance after withdrawl'); |
79 | is($savings_account->balance, 350, '... got the right savings balance after checking withdrawl (no overdraft)'); |
80 | |
81 | lives_ok { |
82 | $checking_account->withdraw(200); |
83 | } '... withdrew from checking successfully'; |
84 | is($checking_account->balance, 0, '... got the right checkings balance after withdrawl'); |
85 | is($savings_account->balance, 200, '... got the right savings balance after overdraft withdrawl'); |
86 | } |
ad1ac1bd |
87 | |
703d9522 |
88 | { |
89 | my $checking_account = CheckingAccount->new( |
90 | balance => 100 |
91 | # no overdraft account |
92 | ); |
93 | isa_ok($checking_account, 'CheckingAccount'); |
94 | isa_ok($checking_account, 'BankAccount'); |
95 | |
96 | is($checking_account->overdraft_account, undef, '... no overdraft account'); |
97 | |
98 | is($checking_account->balance, 100, '... got the right checkings balance'); |
99 | |
100 | lives_ok { |
101 | $checking_account->withdraw(50); |
102 | } '... withdrew from checking successfully'; |
103 | is($checking_account->balance, 50, '... got the right checkings balance after withdrawl'); |
104 | |
105 | dies_ok { |
106 | $checking_account->withdraw(200); |
107 | } '... withdrawl failed due to attempted overdraft'; |
108 | is($checking_account->balance, 50, '... got the right checkings balance after withdrawl failure'); |
109 | } |
ad1ac1bd |
110 | |
ad1ac1bd |
111 | |