| File: | blib/lib/Test/Mocha/SpyBase.pm |
| Coverage: | 98.5% |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | package Test::Mocha::SpyBase; | ||||||
| 2 | # ABSTRACT: Abstract base class for Spy and Mock | ||||||
| 3 | $Test::Mocha::SpyBase::VERSION = '0.61'; | ||||||
| 4 | 12 12 12 | 3985 10 209 | use strict; | ||||
| 5 | 12 12 12 | 24 20 170 | use warnings; | ||||
| 6 | |||||||
| 7 | 12 12 12 | 23 155 353 | use Carp 1.22 'croak'; | ||||
| 8 | 12 12 12 | 3797 289814 67 | use Types::Standard qw( ArrayRef HashRef ); | ||||
| 9 | |||||||
| 10 | # class attributes | ||||||
| 11 | our $CaptureMode = 0; | ||||||
| 12 | my $NumMethodCalls = 0; | ||||||
| 13 | my $LastMethodCall; | ||||||
| 14 | |||||||
| 15 | ## no critic (NamingConventions::Capitalization) | ||||||
| 16 | sub __CaptureMode { | ||||||
| 17 | 273 | 178 | my ( $class, $value ) = @_; | ||||
| 18 | 273 | 399 | return $CaptureMode; | ||||
| 19 | } | ||||||
| 20 | |||||||
| 21 | sub __NumMethodCalls { | ||||||
| 22 | 262 | 146 | my ( $class, $value ) = @_; | ||||
| 23 | |||||||
| 24 | 262 | 250 | if ( defined $value ) { | ||||
| 25 | 131 | 86 | $NumMethodCalls = $value; | ||||
| 26 | } | ||||||
| 27 | 262 | 280 | return $NumMethodCalls; | ||||
| 28 | } | ||||||
| 29 | |||||||
| 30 | sub __LastMethodCall { | ||||||
| 31 | 131 | 79 | my ( $class, $value ) = @_; | ||||
| 32 | |||||||
| 33 | 131 | 130 | if ( defined $value ) { | ||||
| 34 | 131 | 74 | $LastMethodCall = $value; | ||||
| 35 | } | ||||||
| 36 | 131 | 109 | return $LastMethodCall; | ||||
| 37 | } | ||||||
| 38 | ## use critic | ||||||
| 39 | |||||||
| 40 | sub __new { | ||||||
| 41 | 34 | 81 | my %args = ( | ||||
| 42 | calls => [], # ArrayRef[ MethodCall ] | ||||||
| 43 | stubs => {}, # $method_name => ArrayRef[ MethodStub ] | ||||||
| 44 | ); | ||||||
| 45 | 34 | 55 | return \%args; | ||||
| 46 | } | ||||||
| 47 | |||||||
| 48 | sub __calls { | ||||||
| 49 | 244 | 353 | my ($self) = @_; | ||||
| 50 | 244 | 350 | return $self->{calls}; | ||||
| 51 | } | ||||||
| 52 | |||||||
| 53 | sub __stubs { | ||||||
| 54 | 183 | 99 | my ($self) = @_; | ||||
| 55 | 183 | 203 | return $self->{stubs}; | ||||
| 56 | } | ||||||
| 57 | |||||||
| 58 | sub __find_stub { | ||||||
| 59 | # """ | ||||||
| 60 | # Returns the first stub that satisfies the given method call. | ||||||
| 61 | # Returns undef if no stub is found. | ||||||
| 62 | # """ | ||||||
| 63 | 141 | 87 | my ( $self, $method_call ) = @_; | ||||
| 64 | 141 | 149 | my $stubs = $self->__stubs; | ||||
| 65 | |||||||
| 66 | 141 | 214 | return if !defined $stubs->{ $method_call->name }; | ||||
| 67 | |||||||
| 68 | 62 62 | 43 89 | foreach my $stub ( @{ $stubs->{ $method_call->name } } ) { | ||||
| 69 | 68 | 125 | return $stub if $stub->__satisfied_by($method_call); | ||||
| 70 | } | ||||||
| 71 | 3 | 5 | return; | ||||
| 72 | } | ||||||
| 73 | |||||||
| 74 | sub __capture_method_call { | ||||||
| 75 | # """ | ||||||
| 76 | # Get the last method called on a mock object, | ||||||
| 77 | # removes it from the invocation history, | ||||||
| 78 | # and restores the last method stub response. | ||||||
| 79 | # """ | ||||||
| 80 | 140 | 108 | my ( $class, $coderef ) = @_; | ||||
| 81 | |||||||
| 82 | ### assert: !$CaptureMode | ||||||
| 83 | 140 | 98 | $NumMethodCalls = 0; | ||||
| 84 | 140 | 109 | $LastMethodCall = undef; | ||||
| 85 | { | ||||||
| 86 | # Execute the coderef. This should in turn include a method call on | ||||||
| 87 | # mock, which should be handled by its AUTOLOAD method. | ||||||
| 88 | 140 140 | 362 278 | local $CaptureMode = 1; | ||||
| 89 | 140 | 170 | $coderef->(); | ||||
| 90 | } | ||||||
| 91 | |||||||
| 92 | 131 | 256 | croak 'Coderef must have a method invoked on a mock object' | ||||
| 93 | if $NumMethodCalls == 0; | ||||||
| 94 | 130 | 214 | croak 'Coderef must not have multiple methods invoked on a mock object' | ||||
| 95 | if $NumMethodCalls > 1; | ||||||
| 96 | |||||||
| 97 | 129 | 169 | return $LastMethodCall; | ||||
| 98 | } | ||||||
| 99 | |||||||
| 100 | 1; | ||||||