File Coverage

blib/lib/Evo/Test/Mock.pm
Criterion Covered Total %
statement 70 70 100.0
branch 22 30 73.3
condition 3 3 100.0
subroutine 15 15 100.0
pod 0 4 0.0
total 110 122 90.1


line stmt bran cond sub pod time code
1             package Evo::Test::Mock;
2 3     3   2174 use Evo '-Class *; -Export; Carp croak; -Lib eval_want strict_opts; /::Call';
  3         10  
  3         32  
3 3     3   1810 use Hash::Util::FieldHash 'fieldhash';
  3         2236  
  3         744  
4              
5             fieldhash my %REG;
6              
7             has 'original_sub';
8             has 'original_name';
9             has 'calls';
10             has 'sub';
11              
12             our $ORIGINAL;
13              
14 6 50   6 0 28 sub get_original() : prototype() : Export {
  6         12  
15 6 50       33 $ORIGINAL or die "Not in mocked subroutine";
16 3     3   22 }
  3         5  
  3         21  
17              
18 3     3 0 588 sub call_original : Export { get_original->(@_); }
  3     5   7  
  3         11  
  5         29  
19              
20 12 50   12 0 104 sub create_mock ($me, $name, @args) {
  12         25  
  12         23  
  12         41  
  12         22  
21 12         20 my %args;
22 12 100       53 %args = @args == 1 ? (patch => $args[0]) : @args;
23 12         86 my ($patch, $rethrow) = strict_opts \%args, [qw(patch rethrow)], 2;
24              
25 3     3   659 no strict 'refs'; ## no critic
  3         9  
  3         865  
26 12 100       28 my $orig = *{$name}{CODE} or die "No sub $name";
  12         63  
27 11 100       248 croak "$name was already mocked" if $REG{$orig};
28              
29 10 100   2   47 my $mock_sub = ref $patch eq 'CODE' ? $patch : $patch ? sub { call_original(@_) } : sub { };
  2 100       9  
30              
31 10         20 my $calls = [];
32             my $sub = sub {
33 10     10   1604 local $ORIGINAL = $orig;
34 10         40 my $rfn = eval_want wantarray, @_, $mock_sub;
35 10         56 my $err = $@;
36 10         106 my $call = Evo::Test::Call->new(args => \@_, exception => $err, result_fn => $rfn);
37 10         28 push $calls->@*, $call;
38 10 100 100     313 croak $err if !$rfn && $rethrow;
39 9 100       33 return unless $rfn;
40 7         24 $rfn->();
41 10         43 };
42              
43 10         136 my $mock = $me->new(original_sub => $orig, original_name => $name, sub => $sub, calls => $calls);
44              
45 3     3   46 no warnings 'redefine';
  3         8  
  3         542  
46 10         63 $REG{$sub}++;
47 10         24 *{$name} = $sub;
  10         37  
48 10         44 $mock;
49             }
50              
51 7 50   7 0 40 sub get_call ($self, $n) {
  7 50       24  
  7         17  
  7         13  
  7         14  
52 7 50       38 return unless exists $self->calls->[$n];
53 7         50 $self->calls->[$n];
54             }
55              
56 10 50   10   5741 sub DESTROY($self) {
  10 50       31  
  10         22  
  10         19  
57             ## no critic;
58 3     3   24 no strict 'refs';
  3         6  
  3         94  
59 3     3   19 no warnings 'redefine';
  3         5  
  3         273  
60 10         36 *{${\$self->original_name}} = $self->original_sub;
  10         19  
  10         221  
61             }
62              
63              
64             1;
65              
66             __END__