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   1105 use Evo '-Class *; -Export; Carp croak; -Lib eval_want strict_opts; /::Call';
  3         7  
  3         17  
3 3     3   1580 use Hash::Util::FieldHash 'fieldhash';
  3         2056  
  3         393  
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 48 sub get_original() : prototype() : Export {
  6         9  
15 6 50       22 $ORIGINAL or die "Not in mocked subroutine";
16 3     3   19 }
  3         5  
  3         18  
17              
18 3     3 0 418 sub call_original : Export { get_original->(@_); }
  3     5   6  
  3         11  
  5         24  
19              
20 12 50   12 0 85 sub create_mock ($me, $name, @args) {
  12         21  
  12         17  
  12         29  
  12         19  
21 12         19 my %args;
22 12 100       95 %args = @args == 1 ? (patch => $args[0]) : @args;
23 12         48 my ($patch, $rethrow) = strict_opts \%args, [qw(patch rethrow)], 2;
24              
25 3     3   463 no strict 'refs'; ## no critic
  3         7  
  3         662  
26 12 100       25 my $orig = *{$name}{CODE} or die "No sub $name";
  12         53  
27 11 100       230 croak "$name was already mocked" if $REG{$orig};
28              
29 10 100   2   50 my $mock_sub = ref $patch eq 'CODE' ? $patch : $patch ? sub { call_original(@_) } : sub { };
  2 100       7  
30              
31 10         21 my $calls = [];
32             my $sub = sub {
33 10     10   1193 local $ORIGINAL = $orig;
34 10         35 my $rfn = eval_want wantarray, @_, $mock_sub;
35 10         40 my $err = $@;
36 10         82 my $call = Evo::Test::Call->new(args => \@_, exception => $err, result_fn => $rfn);
37 10         24 push $calls->@*, $call;
38 10 100 100     205 croak $err if !$rfn && $rethrow;
39 9 100       23 return unless $rfn;
40 7         23 $rfn->();
41 10         34 };
42              
43 10         118 my $mock = $me->new(original_sub => $orig, original_name => $name, sub => $sub, calls => $calls);
44              
45 3     3   17 no warnings 'redefine';
  3         7  
  3         461  
46 10         55 $REG{$sub}++;
47 10         17 *{$name} = $sub;
  10         31  
48 10         35 $mock;
49             }
50              
51 7 50   7 0 28 sub get_call ($self, $n) {
  7 50       18  
  7         13  
  7         10  
  7         9  
52 7 50       29 return unless exists $self->calls->[$n];
53 7         40 $self->calls->[$n];
54             }
55              
56 10 50   10   3659 sub DESTROY($self) {
  10 50       25  
  10         18  
  10         15  
57             ## no critic;
58 3     3   18 no strict 'refs';
  3         5  
  3         69  
59 3     3   12 no warnings 'redefine';
  3         9  
  3         232  
60 10         25 *{${\$self->original_name}} = $self->original_sub;
  10         13  
  10         156  
61             }
62              
63              
64             1;
65              
66             __END__