File Coverage

blib/lib/Test/Spec/RMock/MockObject.pm
Criterion Covered Total %
statement 70 70 100.0
branch 13 14 92.8
condition 5 8 62.5
subroutine 14 14 100.0
pod 0 6 0.0
total 102 112 91.0


line stmt bran cond sub pod time code
1             package Test::Spec::RMock::MockObject;
2              
3             sub new {
4 26     26 0 36 my ($class, $name) = @_;
5 26         129 my $self = {
6             _name => $name,
7             _messages => {},
8             _problems_found => [],
9             _canceled => 0,
10             _is_null_object => 0,
11             };
12 26         74 bless $self, $class;
13 26   33     81 my $context = Test::Spec->current_context
14             || Carp::croak "Test::Spec::RMocks only works in conjunction with Test::Spec";
15 26     46   230 $context->on_leave(sub { $self->__teardown });
  46         12469  
16 26         246 $self;
17             }
18              
19             sub should_receive {
20 25     25 0 975 my ($self, $message) = @_;
21 25         81 my $expectation = Test::Spec::RMock::MessageExpectation->new($message);
22 25         69 $self->__register_expectation($message, $expectation);
23 25         95 $expectation;
24             }
25              
26             sub should_not_receive {
27 2     2 0 9 my ($self, $message) = @_;
28 2         5 $self->should_receive($message)->exactly(0)->times;
29             }
30              
31             sub stub {
32 6     6 0 501 my ($self, %spec) = @_;
33 6         7 my $last_double;
34 6         50 while (my ($method_name, $return_value) = each %spec) {
35 8         22 $last_double = $self->should_receive($method_name)->and_return($return_value)->any_number_of_times;
36             }
37 6         20 $last_double;
38             }
39              
40             sub stub_chain {
41 3     3 0 11 my ($self, @chain) = @_;
42 3         6 my $name = shift @chain;
43 3 100       9 if (@chain) {
44 2         6 my $next = __PACKAGE__->new('StubChainMockObject');
45 2         5 $self->stub($name => $next);
46 2         8 return $next->stub_chain(@chain);
47             }
48 1         3 $self->stub($name => undef);
49             }
50              
51             sub as_null_object {
52 2     2 0 9 my ($self) = @_;
53 2         3 $self->{_is_null_object} = 1;
54 2         5 $self;
55             }
56              
57             sub __cancel {
58 14     14   21 my ($self) = @_;
59 14         27 $self->{_canceled} = 1;
60 14         35 $self;
61             }
62              
63             sub __register_expectation {
64 25     25   45 my ($self, $message, $expectation) = @_;
65 25   100     135 $self->{_messages}{$message} ||= [];
66 25         27 push @{$self->{_messages}{$message}}, $expectation;
  25         69  
67             }
68              
69              
70             sub __teardown {
71 46     46   59 my ($self) = @_;
72 46         74 my $report = $self->__check;
73 46 50 66     170 die $report if !$self->{_canceled} && $report;
74 46         110 return 1;
75             }
76              
77             sub __check {
78 61     61   91 my ($self) = @_;
79 61         66 for my $ms (values %{$self->{_messages}}) {
  61         161  
80 52         89 for my $m (@$ms) {
81 58 100       149 push @{$self->{_problems_found}}, $m->call_contraint_error_message($self->{_name}) unless $m->is_call_constrint_satisfied;
  6         24  
82             }
83             }
84 61         101 join("\n", @{$self->{_problems_found}});
  61         227  
85             }
86              
87             sub __find_method_proxy {
88 29     29   48 my ($self, $expectations, @args) = @_;
89 29         47 for my $e (@$expectations) {
90 33 100       88 return $e if $e->is_all_conditions_satisfied(@args);
91             }
92 4         13 for my $e (@$expectations) {
93 4 100       13 return $e if $e->does_arguments_match(@args);
94             }
95 2         6 for my $e (@$expectations) {
96 2         3 push @{$self->{_problems_found}}, $e->argument_matching_error_message(@args);
  2         11  
97             }
98 2         329 return $expectations->[0];
99             }
100              
101             our $AUTOLOAD;
102             sub AUTOLOAD {
103 34     34   487 my ($self, @args) = @_;
104 34         66 my $message_name = $self->__get_message_name;
105 34         64 my $expectations = $self->{_messages}{$message_name};
106 34 100       75 unless ($expectations) {
107 5 100       21 return $self if $self->{_is_null_object};
108 2         10 push @{$self->{_problems_found}},
  3         13  
109             sprintf("Unmocked method '%s' called on '%s' with (%s)",
110             $message_name,
111             $self->{_name},
112 2         3 join(', ', map {"'$_'"} @args));
113 2         135 return;
114             }
115 29         63 my $proxy = $self->__find_method_proxy($expectations, @args);
116 29         100 return $proxy->call(@args);
117             }
118              
119             sub __get_message_name {
120 34     34   48 my $name = $AUTOLOAD;
121 34         167 $name =~ s/.*:://;
122 34         80 $name;
123             }
124              
125             1;
126              
127             __END__