Commit | Line | Data |
ddc8edba |
1 | #!/usr/bin/perl |
2 | |
3 | use strict; |
4 | use warnings; |
5 | |
efd3d14c |
6 | use Test::More tests => 19; |
ddc8edba |
7 | use Test::Exception; |
8 | |
efd3d14c |
9 | use Class::MOP; |
ddc8edba |
10 | |
11 | { |
12 | package BankAccount; |
13 | |
14 | use strict; |
15 | use warnings; |
16 | use metaclass; |
17 | |
18 | use Carp 'confess'; |
19 | |
1aeb4c53 |
20 | BankAccount->meta->add_attribute('balance' => ( |
ddc8edba |
21 | accessor => 'balance', |
22 | init_arg => 'balance', |
23 | default => 0 |
24 | )); |
25 | |
26 | sub new { (shift)->meta->new_object(@_) } |
96ceced8 |
27 | |
ddc8edba |
28 | sub deposit { |
29 | my ($self, $amount) = @_; |
ddc8edba |
30 | $self->balance($self->balance + $amount); |
31 | } |
32 | |
33 | sub withdraw { |
a4258ffd |
34 | my ($self, $amount) = @_; |
35 | my $current_balance = $self->balance(); |
36 | ($current_balance >= $amount) |
ddc8edba |
37 | || confess "Account overdrawn"; |
ddc8edba |
38 | $self->balance($current_balance - $amount); |
39 | } |
40 | |
41 | package CheckingAccount; |
42 | |
43 | use strict; |
44 | use warnings; |
96ceced8 |
45 | use metaclass; |
46 | |
ddc8edba |
47 | use base 'BankAccount'; |
48 | |
1aeb4c53 |
49 | CheckingAccount->meta->add_attribute('overdraft_account' => ( |
ddc8edba |
50 | accessor => 'overdraft_account', |
51 | init_arg => 'overdraft', |
52 | )); |
53 | |
a4258ffd |
54 | CheckingAccount->meta->add_before_method_modifier('withdraw' => sub { |
ddc8edba |
55 | my ($self, $amount) = @_; |
ddc8edba |
56 | my $overdraft_amount = $amount - $self->balance(); |
57 | if ($overdraft_amount > 0) { |
ddc8edba |
58 | $self->overdraft_account->withdraw($overdraft_amount); |
59 | $self->deposit($overdraft_amount); |
60 | } |
ddc8edba |
61 | }); |
62 | |
63 | ::ok(CheckingAccount->meta->has_method('withdraw'), '... checking account now has a withdraw method'); |
195f5bf8 |
64 | ::isa_ok(CheckingAccount->meta->get_method('withdraw'), 'Class::MOP::Method::Wrapped'); |
65 | ::isa_ok(BankAccount->meta->get_method('withdraw'), 'Class::MOP::Method'); |
ddc8edba |
66 | } |
67 | |
68 | |
69 | my $savings_account = BankAccount->new(balance => 250); |
70 | isa_ok($savings_account, 'BankAccount'); |
71 | |
72 | is($savings_account->balance, 250, '... got the right savings balance'); |
73 | lives_ok { |
74 | $savings_account->withdraw(50); |
75 | } '... withdrew from savings successfully'; |
76 | is($savings_account->balance, 200, '... got the right savings balance after withdrawl'); |
195f5bf8 |
77 | dies_ok { |
78 | $savings_account->withdraw(250); |
79 | } '... could not withdraw from savings successfully'; |
80 | |
ddc8edba |
81 | |
82 | $savings_account->deposit(150); |
83 | is($savings_account->balance, 350, '... got the right savings balance after deposit'); |
84 | |
85 | my $checking_account = CheckingAccount->new( |
86 | balance => 100, |
87 | overdraft => $savings_account |
88 | ); |
89 | isa_ok($checking_account, 'CheckingAccount'); |
90 | isa_ok($checking_account, 'BankAccount'); |
91 | |
92 | is($checking_account->overdraft_account, $savings_account, '... got the right overdraft account'); |
93 | |
94 | is($checking_account->balance, 100, '... got the right checkings balance'); |
95 | |
96 | lives_ok { |
96ceced8 |
97 | $checking_account->withdraw(50); |
ddc8edba |
98 | } '... withdrew from checking successfully'; |
96ceced8 |
99 | is($checking_account->balance, 50, '... got the right checkings balance after withdrawl'); |
100 | is($savings_account->balance, 350, '... got the right savings balance after checking withdrawl (no overdraft)'); |
ddc8edba |
101 | |
96ceced8 |
102 | lives_ok { |
103 | $checking_account->withdraw(200); |
104 | } '... withdrew from checking successfully'; |
ddc8edba |
105 | is($checking_account->balance, 0, '... got the right checkings balance after withdrawl'); |
96ceced8 |
106 | is($savings_account->balance, 200, '... got the right savings balance after overdraft withdrawl'); |
ddc8edba |
107 | |