line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
=pod |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Test::Mockify - minimal mocking framework for perl |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 SYNOPSIS |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
use Test::Mockify; |
10
|
|
|
|
|
|
|
use Test::Mockify::Verify qw ( WasCalled ); |
11
|
|
|
|
|
|
|
use Test::Mockify::Matcher qw ( String ); |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
# build a new mocked object |
14
|
|
|
|
|
|
|
my $MockObjectBuilder = Test::Mockify->new('SampleLogger', []); |
15
|
|
|
|
|
|
|
$MockObjectBuilder->mock('log')->when(String())->thenReturnUndef(); |
16
|
|
|
|
|
|
|
my $MockedLogger = $MockLoggerBuilder->getMockObject(); |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# inject mocked object into the code you want to test |
19
|
|
|
|
|
|
|
my $App = SampleApp->new('logger'=> $MockedLogger); |
20
|
|
|
|
|
|
|
$App->do_something(); |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# verify that the mocked method was called |
23
|
|
|
|
|
|
|
ok(WasCalled($MockedLogger, 'log'), 'log was called'); |
24
|
|
|
|
|
|
|
done_testing(); |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
=head1 DESCRIPTION |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
Use L<Test::Mockify> to create and configure mock objects. Use L<Test::Mockify::Verify> to |
29
|
|
|
|
|
|
|
verify the interactions with your mocks. |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
=head1 METHODS |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
=cut |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
package Test::Mockify; |
36
|
4
|
|
|
4
|
|
61000
|
use Test::Mockify::Tools qw ( Error ExistsMethod IsValid LoadPackage Isa ); |
|
4
|
|
|
|
|
12
|
|
|
4
|
|
|
|
|
305
|
|
37
|
4
|
|
|
4
|
|
1448
|
use Test::Mockify::TypeTests qw ( IsInteger IsFloat IsString IsArrayReference IsHashReference IsObjectReference ); |
|
4
|
|
|
|
|
4
|
|
|
4
|
|
|
|
|
221
|
|
38
|
4
|
|
|
4
|
|
1282
|
use Test::Mockify::MethodCallCounter; |
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
105
|
|
39
|
4
|
|
|
4
|
|
1686
|
use Test::Mockify::Method; |
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
159
|
|
40
|
4
|
|
|
4
|
|
1360
|
use Test::Mockify::MethodSpy; |
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
120
|
|
41
|
4
|
|
|
4
|
|
2140
|
use Test::MockObject::Extends; |
|
4
|
|
|
|
|
22990
|
|
|
4
|
|
|
|
|
17
|
|
42
|
4
|
|
|
4
|
|
1545
|
use Test::Mockify::CompatibilityTools qw (MigrateOldMatchers); |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
205
|
|
43
|
4
|
|
|
4
|
|
19
|
use Data::Dumper; |
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
155
|
|
44
|
4
|
|
|
4
|
|
13
|
use Scalar::Util qw( blessed ); |
|
4
|
|
|
|
|
4
|
|
|
4
|
|
|
|
|
176
|
|
45
|
4
|
|
|
4
|
|
15
|
use Data::Compare; |
|
4
|
|
|
|
|
4
|
|
|
4
|
|
|
|
|
26
|
|
46
|
|
|
|
|
|
|
|
47
|
4
|
|
|
4
|
|
7071
|
use experimental 'switch'; |
|
4
|
|
|
|
|
10772
|
|
|
4
|
|
|
|
|
22
|
|
48
|
|
|
|
|
|
|
|
49
|
4
|
|
|
4
|
|
481
|
use strict; |
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
5943
|
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
our $VERSION = '0.10.1'; |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub new { |
54
|
59
|
|
|
59
|
0
|
9253
|
my $class = shift; |
55
|
59
|
|
|
|
|
70
|
my ( $FakeModulePath, $aFakeParams ) = @_; |
56
|
|
|
|
|
|
|
|
57
|
59
|
|
|
|
|
91
|
my $self = bless {}, $class; |
58
|
|
|
|
|
|
|
|
59
|
59
|
|
|
|
|
152
|
LoadPackage( $FakeModulePath ); |
60
|
59
|
|
|
|
|
53
|
my $FakeClass = $FakeModulePath->new( @{$aFakeParams} ); |
|
59
|
|
|
|
|
175
|
|
61
|
59
|
|
|
|
|
403
|
$self->_mockedModulPath($FakeModulePath); |
62
|
59
|
|
|
|
|
213
|
$self->_mockedSelf(Test::MockObject::Extends->new( $FakeClass )); |
63
|
59
|
|
|
|
|
98
|
$self->_initMockedModule(); |
64
|
|
|
|
|
|
|
|
65
|
59
|
|
|
|
|
106
|
return $self; |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub _mockedModulPath { |
70
|
143
|
|
|
143
|
|
113
|
my $self = shift; |
71
|
143
|
|
|
|
|
116
|
my ($ModulPath) = @_; |
72
|
143
|
100
|
|
|
|
409
|
return $self->{'MockedModulePath'} unless ($ModulPath); |
73
|
59
|
|
|
|
|
111
|
$self->{'MockedModulePath'} = $ModulPath; |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
sub _mockedSelf { |
77
|
510
|
|
|
510
|
|
4655
|
my $self = shift; |
78
|
510
|
|
|
|
|
390
|
my ($MockedSelf) = @_; |
79
|
510
|
100
|
|
|
|
1999
|
return $self->{'MockedModule'} unless ($MockedSelf); |
80
|
59
|
|
|
|
|
84
|
$self->{'MockedModule'} = $MockedSelf; |
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
sub _initMockedModule { |
84
|
59
|
|
|
59
|
|
52
|
my $self = shift; |
85
|
|
|
|
|
|
|
|
86
|
59
|
|
|
|
|
170
|
$self->_mockedSelf()->{'__MethodCallCounter'} = Test::Mockify::MethodCallCounter->new(); |
87
|
59
|
|
|
|
|
81
|
$self->_mockedSelf()->{'__isMockified'} = 1; |
88
|
59
|
|
|
|
|
99
|
$self->_addGetParameterFromMockifyCall(); |
89
|
|
|
|
|
|
|
|
90
|
59
|
|
|
|
|
67
|
return; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
=pod |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=head2 getMockObject |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
Provides the actual mock object, which you can use in the test. |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
my $aParameterList = ['SomeValueForConstructor']; |
101
|
|
|
|
|
|
|
my $MockObjectBuilder = Test::Mockify->new( 'My::Module', $aParameterList ); |
102
|
|
|
|
|
|
|
my $MyModuleObject = $MockObjectBuilder->getMockObject(); |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=cut |
105
|
|
|
|
|
|
|
sub getMockObject { |
106
|
56
|
|
|
56
|
1
|
123
|
my $self = shift; |
107
|
56
|
|
|
|
|
83
|
return $self->_mockedSelf(); |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=pod |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=head2 mock |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
This is place where the mocked methods are defined. The method also proves that the method you like to mock actually exists. |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=head3 synopsis |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
This method takes one parameter, which is the name of the method you like to mock. |
120
|
|
|
|
|
|
|
Because you need to specify more detailed the behaviour of this mock you have to chain the method signature (when) and the expected return value (then...). |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
For example, the next line will create a mocked version of the method log, but only if this method is called with any string and the number 123. In this case it will return the String 'Hello World'. Mockify will throw an error if this method is called somehow else. |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
my $MockObjectBuilder = Test::Mockify->new( 'Sample::Logger', [] ); |
125
|
|
|
|
|
|
|
$MockObjectBuilder->mock('log')->when(String(), Number(123))->thenReturn('Hello World'); |
126
|
|
|
|
|
|
|
my $SampleLogger = $MockObjectBuilder->getMockObject(); |
127
|
|
|
|
|
|
|
is($SampleLogger->log('abc',123), 'Hello World'); |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=head4 when |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
To define the signature in the needed structure you must use the L<< Test::Mockify::Matcher >>. |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=head4 whenAny |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
If you don't want to specify the method signature at all, you can use whenAny. |
137
|
|
|
|
|
|
|
It is not possible to mix C<whenAny> and C<when> for the same method. |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=head4 then ... |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
For possible return types please look in L<Test::Mockify::ReturnValue> |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=cut |
144
|
|
|
|
|
|
|
sub mock { |
145
|
20
|
|
|
20
|
1
|
71
|
my $self = shift; |
146
|
20
|
|
|
|
|
30
|
my @Parameters = @_; |
147
|
|
|
|
|
|
|
|
148
|
20
|
|
|
|
|
23
|
my $ParameterAmount = scalar @Parameters; |
149
|
20
|
100
|
66
|
|
|
72
|
if($ParameterAmount == 1 && IsString($Parameters[0]) ){ |
150
|
17
|
|
|
|
|
32
|
return $self->_addMockWithMethod($Parameters[0]); |
151
|
|
|
|
|
|
|
} |
152
|
3
|
100
|
|
|
|
6
|
if($ParameterAmount == 2){ |
153
|
2
|
|
|
|
|
4
|
my ( $MethodName, $ReturnValueOrFunctionPointer ) = @Parameters; |
154
|
2
|
100
|
|
|
|
6
|
if( ref($ReturnValueOrFunctionPointer) eq 'CODE' ){ |
155
|
1
|
|
|
|
|
3
|
$self->addMock($MethodName, $ReturnValueOrFunctionPointer); |
156
|
|
|
|
|
|
|
}else{ |
157
|
1
|
|
|
|
|
4
|
$self->addMockWithReturnValue($MethodName, $ReturnValueOrFunctionPointer); |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
} |
160
|
3
|
100
|
|
|
|
6
|
if($ParameterAmount == 3){ |
161
|
1
|
|
|
|
|
3
|
my ( $MethodName, $ReturnValue, $aParameterTypes ) = @_; |
162
|
1
|
|
|
|
|
4
|
$self->addMockWithReturnValueAndParameterCheck($MethodName, $ReturnValue, $aParameterTypes); |
163
|
|
|
|
|
|
|
} |
164
|
3
|
|
|
|
|
6
|
return; |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
=pod |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=head2 spy |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
Use spy if you want to observe a method. You can use the L<Test::Mockify::Verify> to ensure that the method was called with the expected parameters. |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=head3 synopsis |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
This method takes one parameter, which is the name of the method you like to spy. |
175
|
|
|
|
|
|
|
Because you need to specify more detailed the behaviour of this spy you have to define the method signature with C<when> |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
For example, the next line will create a method spy of the method log, but only if this method is called with any string and the number 123. Mockify will throw an error if this method is called in another way. |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
my $MockObjectBuilder = Test::Mockify->new( 'Sample::Logger', [] ); |
180
|
|
|
|
|
|
|
$MockObjectBuilder->spy('log')->when(String(), Number(123)); |
181
|
|
|
|
|
|
|
my $SampleLogger = $MockObjectBuilder->getMockObject(); |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
# call spied method |
184
|
|
|
|
|
|
|
$SampleLogger->log('abc', 123); |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
# verify that the spied method was called |
187
|
|
|
|
|
|
|
is_deeply(GetParametersFromMockifyCall($MockedLogger, 'log'),['abc', 123], 'Check parameters of first call'); |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
=head4 when |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
To define the signature in the needed structure you must use the L<< Test::Mockify::Matcher >>. |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=head4 whenAny |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
If you don't want to specify the method signature at all, you can use whenAny. |
196
|
|
|
|
|
|
|
It is not possible to mix C<whenAny> and C<when> for the same method. |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=cut |
199
|
|
|
|
|
|
|
sub spy { |
200
|
16
|
|
|
16
|
1
|
43
|
my $self = shift; |
201
|
16
|
|
|
|
|
21
|
my ($MethodName) = @_; |
202
|
16
|
|
|
|
|
13
|
my $PointerOriginalMethod = \&{$self->_mockedModulPath().'::'.$MethodName}; |
|
16
|
|
|
|
|
24
|
|
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
return $self->_addMockWithMethodSpy($MethodName, sub { |
205
|
15
|
|
|
15
|
|
23
|
return $PointerOriginalMethod->($self->_mockedSelf(), @_); |
206
|
16
|
|
|
|
|
60
|
}); |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
=pod |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
=head2 addMethodSpy I<(deprecated)> |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
With this method it is possible to observe a method. That means, you keep the original functionality but you can get meta data from the mockify-framework. |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
$MockObjectBuilder->addMethodSpy('myMethodName'); |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
=cut |
219
|
|
|
|
|
|
|
sub addMethodSpy { |
220
|
2
|
|
|
2
|
1
|
9
|
my $self = shift; |
221
|
2
|
|
|
|
|
3
|
my ( $MethodName ) = @_; |
222
|
2
|
50
|
|
|
|
28
|
if (warnings::enabled("deprecated")) { |
223
|
0
|
|
|
|
|
0
|
warnings::warn('deprecated', "addMethodSpy is deprecated, use spy('name')->whenAny()"); |
224
|
|
|
|
|
|
|
} |
225
|
2
|
|
|
|
|
143
|
$self->spy($MethodName)->whenAny(); |
226
|
2
|
|
|
|
|
4
|
return; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
=pod |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
=head2 addMethodSpyWithParameterCheck I<(deprecated)> |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
With this method it is possible to observe a method and check the parameters. That means, you keep the original functionality, but you can get meta data from the mockify- framework and use the parameter check, like B<addMockWithReturnValueAndParameterCheck>. |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
my $aParameterTypes = [String(),String(abcd)]; |
236
|
|
|
|
|
|
|
$MockObjectBuilder->addMethodSpyWithParameterCheck('myMethodName', $aParameterTypes); |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
To define it in a nice way the signature you must use the L<< Test::Mockify::Matcher; >>. |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
=cut |
241
|
|
|
|
|
|
|
sub addMethodSpyWithParameterCheck { |
242
|
2
|
|
|
2
|
1
|
14
|
my $self = shift; |
243
|
2
|
|
|
|
|
3
|
my ( $MethodName, $aParameterTypes ) = @_; |
244
|
2
|
50
|
|
|
|
36
|
if (warnings::enabled("deprecated")) { |
245
|
0
|
|
|
|
|
0
|
warnings::warn('deprecated', "addMethodSpyWithParameterCheck is deprecated, use spy('name')->when(String('abc'))"); |
246
|
|
|
|
|
|
|
} |
247
|
2
|
|
|
|
|
197
|
my $aMigratedMatchers = MigrateOldMatchers($aParameterTypes); |
248
|
2
|
|
|
|
|
5
|
$self->spy($MethodName)->when(@{$aMigratedMatchers}); |
|
2
|
|
|
|
|
9
|
|
249
|
2
|
|
|
|
|
6
|
return; |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
=pod |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
=head2 addMock I<(deprecated)> |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
This is the simplest case. It works like the mock-method from L<Test::MockObject>. |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
Only handover the B<name> and a B<method pointer>. Mockify will automatically check if the method exists in the original object. |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
$MockObjectBuilder->addMock('myMethodName', sub { |
262
|
|
|
|
|
|
|
# Your implementation |
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
); |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=cut |
267
|
|
|
|
|
|
|
sub addMock { |
268
|
7
|
|
|
7
|
1
|
35
|
my $self = shift; |
269
|
7
|
|
|
|
|
7
|
my ( $MethodName, $rSub ) = @_; |
270
|
7
|
50
|
|
|
|
96
|
if (warnings::enabled("deprecated")) { |
271
|
0
|
|
|
|
|
0
|
warnings::warn('deprecated', "addMock is deprecated, use mock('name')->whenAny()->thenCall(sub{})"); |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
$self->_addMockWithMethod($MethodName)->whenAny()->thenCall(sub { |
274
|
7
|
|
|
7
|
|
9
|
return $rSub->($self->_mockedSelf(), @_); |
275
|
7
|
|
|
|
|
535
|
}); |
276
|
|
|
|
|
|
|
|
277
|
7
|
|
|
|
|
10
|
return; |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
sub _addMockWithMethod { |
281
|
53
|
|
|
53
|
|
74
|
my $self = shift; |
282
|
53
|
|
|
|
|
54
|
my ( $MethodName ) = @_; |
283
|
53
|
|
|
|
|
82
|
$self->_testMockTypeUsage($MethodName); |
284
|
52
|
|
|
|
|
138
|
return $self->_addMock($MethodName, Test::Mockify::Method->new()); |
285
|
|
|
|
|
|
|
} |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
sub _addMockWithMethodSpy { |
288
|
16
|
|
|
16
|
|
11
|
my $self = shift; |
289
|
16
|
|
|
|
|
19
|
my ( $MethodName, $PointerOriginalMethod ) = @_; |
290
|
16
|
|
|
|
|
23
|
$self->_testMockTypeUsage($MethodName); |
291
|
15
|
|
|
|
|
45
|
return $self->_addMock($MethodName, Test::Mockify::MethodSpy->new($PointerOriginalMethod)); |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
sub _addMock { |
295
|
67
|
|
|
67
|
|
62
|
my $self = shift; |
296
|
67
|
|
|
|
|
75
|
my ( $MethodName, $Method) = @_; |
297
|
|
|
|
|
|
|
|
298
|
67
|
|
|
|
|
91
|
ExistsMethod( $self->_mockedModulPath(), $MethodName ); |
299
|
66
|
|
|
|
|
96
|
$self->_mockedSelf()->{'__MethodCallCounter'}->addMethod( $MethodName ); |
300
|
66
|
100
|
|
|
|
132
|
if(not $self->{'MethodStore'}{$MethodName}){ |
301
|
56
|
|
33
|
|
|
211
|
$self->{'MethodStore'}{$MethodName} //= $Method; |
302
|
|
|
|
|
|
|
$self->_mockedSelf()->mock($MethodName, sub { |
303
|
74
|
|
|
74
|
|
8580
|
$self->_mockedSelf()->{'__MethodCallCounter'}->increment( $MethodName ); |
304
|
74
|
|
|
|
|
69
|
my $MockedSelf = shift; |
305
|
74
|
|
|
|
|
90
|
my @MockedParameters = @_; |
306
|
74
|
|
|
|
|
117
|
$self->_storeParameters( $MethodName, $MockedSelf, \@MockedParameters ); |
307
|
74
|
|
|
|
|
214
|
return $self->{'MethodStore'}{$MethodName}->call(@MockedParameters); |
308
|
56
|
|
|
|
|
78
|
}); |
309
|
|
|
|
|
|
|
} |
310
|
66
|
|
|
|
|
1414
|
return $self->{'MethodStore'}{$MethodName}; |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
=pod |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
=head2 addMockWithReturnValue I<(deprecated)> |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
Does the same as C<addMock>, but here you can handover a B<value> which will be returned if you call the mocked method. |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
$MockObjectBuilder->addMockWithReturnValue('myMethodName','the return value'); |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
=cut |
322
|
|
|
|
|
|
|
sub addMockWithReturnValue { |
323
|
5
|
|
|
5
|
1
|
51
|
my $self = shift; |
324
|
5
|
|
|
|
|
8
|
my ( $MethodName, $ReturnValue ) = @_; |
325
|
5
|
50
|
|
|
|
62
|
if (warnings::enabled("deprecated")) { |
326
|
0
|
|
|
|
|
0
|
warnings::warn('deprecated', "addMockWithReturnValue is deprecated, use mock('name')->when()->thenReturn('Value')"); |
327
|
|
|
|
|
|
|
} |
328
|
5
|
50
|
|
|
|
442
|
if($ReturnValue){ |
329
|
5
|
|
|
|
|
11
|
$self->_addMockWithMethod($MethodName)->when()->thenReturn($ReturnValue); |
330
|
|
|
|
|
|
|
}else { |
331
|
0
|
|
|
|
|
0
|
$self->_addMockWithMethod($MethodName)->when()->thenReturnUndef(); |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
|
334
|
4
|
|
|
|
|
8
|
return; |
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
=pod |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
=head2 addMockWithReturnValueAndParameterCheck I<(deprecated)> |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
This method is an extension of B<addMockWithReturnValue>. Here you can also check the parameters which will be passed. |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
You can check if they have a specific B<data type> or even check if they have a given B<value>. |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
In the following example two strings will be expected, and the second one has to have the value "abcd". |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
my $aParameterTypes = [String(),String('abcd')]; |
348
|
|
|
|
|
|
|
$MockObjectBuilder->addMockWithReturnValueAndParameterCheck('myMethodName','the return value',$aParameterTypes); |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
To define it in a nice way the signature you must use the L<< Test::Mockify::Matcher; >>. |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
=cut |
353
|
|
|
|
|
|
|
sub addMockWithReturnValueAndParameterCheck { |
354
|
26
|
|
|
26
|
1
|
207
|
my $self = shift; |
355
|
26
|
|
|
|
|
32
|
my ( $MethodName, $ReturnValue, $aParameterTypes ) = @_; |
356
|
26
|
50
|
|
|
|
365
|
if (warnings::enabled("deprecated")) { |
357
|
0
|
|
|
|
|
0
|
warnings::warn('deprecated', "addMockWithReturnValue is deprecated, use mock('name')->when(String('abc'))->thenReturn('Value')"); |
358
|
|
|
|
|
|
|
} |
359
|
26
|
100
|
|
|
|
1960
|
if ( not IsArrayReference( $aParameterTypes ) ){ |
360
|
1
|
|
|
|
|
3
|
Error( 'ParameterTypesNotProvided', { |
361
|
|
|
|
|
|
|
'Method' => $self->_mockedModulPath()."->$MethodName", |
362
|
|
|
|
|
|
|
'ParameterList' => $aParameterTypes, |
363
|
|
|
|
|
|
|
} ); |
364
|
|
|
|
|
|
|
} |
365
|
25
|
|
|
|
|
53
|
$aParameterTypes = MigrateOldMatchers($aParameterTypes); |
366
|
|
|
|
|
|
|
|
367
|
24
|
100
|
|
|
|
33
|
if($ReturnValue){ |
368
|
18
|
|
|
|
|
39
|
$self->_addMockWithMethod($MethodName)->when(@{$aParameterTypes})->thenReturn($ReturnValue); |
|
18
|
|
|
|
|
45
|
|
369
|
|
|
|
|
|
|
}else { |
370
|
6
|
|
|
|
|
14
|
$self->_addMockWithMethod($MethodName)->when(@{$aParameterTypes})->thenReturnUndef(); |
|
6
|
|
|
|
|
14
|
|
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
|
373
|
24
|
|
|
|
|
61
|
return; |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
sub _storeParameters { |
377
|
74
|
|
|
74
|
|
62
|
my $self = shift; |
378
|
74
|
|
|
|
|
70
|
my ( $MethodName, $MockedSelf, $aMockedParameters ) = @_; |
379
|
|
|
|
|
|
|
|
380
|
74
|
|
|
|
|
40
|
push( @{$MockedSelf->{$MethodName.'_MockifyParams'}}, $aMockedParameters ); |
|
74
|
|
|
|
|
168
|
|
381
|
|
|
|
|
|
|
|
382
|
74
|
|
|
|
|
74
|
return; |
383
|
|
|
|
|
|
|
} |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
sub _addGetParameterFromMockifyCall { |
387
|
59
|
|
|
59
|
|
43
|
my $self = shift; |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
$self->_mockedSelf()->mock('__getParametersFromMockifyCall', |
390
|
|
|
|
|
|
|
sub{ |
391
|
12
|
|
|
12
|
|
522
|
my $MockedSelf = shift; |
392
|
12
|
|
|
|
|
16
|
my ( $MethodName, $Position ) = @_; |
393
|
|
|
|
|
|
|
|
394
|
12
|
|
|
|
|
32
|
my $aParametersFromAllCalls = $MockedSelf->{$MethodName.'_MockifyParams'}; |
395
|
12
|
100
|
|
|
|
32
|
if( ref $aParametersFromAllCalls ne 'ARRAY' ){ |
396
|
1
|
|
|
|
|
6
|
Error( "$MethodName was not called" ); |
397
|
|
|
|
|
|
|
} |
398
|
11
|
100
|
|
|
|
12
|
if( scalar @{$aParametersFromAllCalls} < $Position ) { |
|
11
|
|
|
|
|
24
|
|
399
|
1
|
|
|
|
|
7
|
Error( "$MethodName was not called ".( $Position+1 ).' times',{ |
400
|
|
|
|
|
|
|
'Method' => "$MethodName", |
401
|
|
|
|
|
|
|
'Postion' => $Position, |
402
|
|
|
|
|
|
|
} ); |
403
|
|
|
|
|
|
|
} |
404
|
|
|
|
|
|
|
else { |
405
|
10
|
|
|
|
|
24
|
my $ParameterFromMockifyCall = $MockedSelf->{$MethodName.'_MockifyParams'}[$Position]; |
406
|
10
|
|
|
|
|
48
|
return $ParameterFromMockifyCall; |
407
|
|
|
|
|
|
|
} |
408
|
0
|
|
|
|
|
0
|
return; |
409
|
|
|
|
|
|
|
} |
410
|
59
|
|
|
|
|
78
|
); |
411
|
|
|
|
|
|
|
|
412
|
59
|
|
|
|
|
1432
|
return; |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
sub _testMockTypeUsage { |
416
|
69
|
|
|
69
|
|
57
|
my $self = shift; |
417
|
69
|
|
|
|
|
343
|
my ($MethodName) = @_; |
418
|
69
|
|
|
|
|
55
|
my $PositionInCallerStack = 2; |
419
|
69
|
|
|
|
|
171
|
my $MethodMockType = (caller($PositionInCallerStack))[3]; |
420
|
69
|
100
|
100
|
|
|
578
|
if($self->{'MethodMockType'}{$MethodName} && $self->{'MethodMockType'}{$MethodName} ne $MethodMockType){ |
421
|
2
|
|
|
|
|
18
|
die('It is not possible to mix spy and mock'); |
422
|
|
|
|
|
|
|
}else{ |
423
|
67
|
|
|
|
|
116
|
$self->{'MethodMockType'}{$MethodName} = $MethodMockType; |
424
|
|
|
|
|
|
|
} |
425
|
67
|
|
|
|
|
66
|
return; |
426
|
|
|
|
|
|
|
} |
427
|
|
|
|
|
|
|
1; |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
__END__ |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
=head1 LICENSE |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
Copyright (C) 2017 ePages GmbH |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify |
436
|
|
|
|
|
|
|
it under the same terms as Perl itself. |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
=head1 AUTHOR |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
Christian Breitkreutz E<lt>christianbreitkreutz@gmx.deE<gt> |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
=cut |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
|