File Coverage

blib/lib/Test/CallFlow.pm
Criterion Covered Total %
statement 240 258 93.0
branch 80 148 54.0
condition 52 118 44.0
subroutine 42 42 100.0
pod 21 21 100.0
total 435 587 74.1


line stmt bran cond sub pod time code
1             package Test::CallFlow;
2              
3 8     8   328807 use warnings;
  8         27  
  8         638  
4 8     8   1658 use strict;
  8         15  
  8         270  
5 6     6   5882 use UNIVERSAL qw(can isa);
  6         195  
  6         40  
6 6     6   3507 use Carp;
  6         14  
  6         458  
7 6     6   31 use Exporter;
  6         14  
  6         383  
8 6     6   34 use File::Spec;
  6         10  
  6         73  
9 6     6   5149 use Test::CallFlow::Plan;
  6         21  
  6         142  
10 6     6   4827 use Test::CallFlow::Call;
  6         29  
  6         108  
11 6     6   5736 use Test::CallFlow::ArgCheck::Any;
  6         18  
  6         65  
12             use vars
13 6     6   219 qw(@ISA @EXPORT_OK %EXPORT_TAGS $recording $planning $running @instances %state @state);
  6         10  
  6         5898  
14              
15             =head1 NAME
16              
17             Test::CallFlow - trivial planning of sub call flows for fast unit test writing.
18              
19             =head1 VERSION
20              
21             Version 0.03
22              
23             =cut
24              
25             our $VERSION = '0.03';
26              
27             =head1 SYNOPSIS
28              
29             Mock packages for planning expected interactions in tests:
30              
31             use Test::CallFlow qw(:all);
32              
33             my $mocked = mock_object( 'My::Mocked::Package::Name' );
34             $mocked->my_method( arg_any(0,9) )->result( 'return value' );
35              
36             mock_run();
37              
38             die "test did not return right value"
39             if $mocked->my_method( 'any', 'arguments' ) ne 'return value';
40              
41             mock_end();
42            
43             =head1 USAGE
44              
45             C functions are used here in a procedural manner
46             because straightforward test scripts are seen as primary use case.
47             As well you may create objects with C and use the provided
48             functions as object methods.
49              
50             =head2 DECLARING
51              
52             use Test::More plan_tests => 1;
53             use Test::CallFlow qw(:all);
54              
55             # just mock a package
56             mock_package( 'Just::Mocked' );
57              
58             # mock a package and make an object of it
59             my $mocked = mock_object(
60             'My::Mocked::Package::Name', # must specify package name
61             { 'optional' => 'content' } ); # may specify what to bless
62              
63             =head2 PLANNING
64              
65             Just::Mocked->new() # no arguments
66             ->result( $mocked ); # return the mock object
67              
68             my $get_call = # refer to this Test::CallFlow::Call object
69             $mocked->get( "FieldX" ) # one equal string argument
70             ->result( 1, 2, 3 ) # return array ( 1, 2, 3 ) on first call
71             ->result( 4, 5, 6 ) # return array ( 4, 5, 6 ) on second call
72             ->result( 7, 8, 9 ) # return array ( 7, 8, 9 ) on any subsequent calls
73             ->min(0) # this call is optional
74             ->max(9) # this call can be made at most 9 times
75             ->anytime; # may be called at this step or any time later
76              
77             $mocked->set( arg_check( qr/^Field/ ), # first argument matching regular expression
78             arg_any( 1, 99 ) ); # 1-99 arguments with any values
79             # return nothing (undef or empty array)
80              
81             $mocked->save( arg_check( \&ok_file ) ) # use own code to check argument
82             ->end( $get_call ); # end scope: $get_call can be made no more
83              
84             # if you wish to use parts of the real package unmocked as is,
85             # load it after planning but before running:
86             use My::Mocked::Package::Name;
87            
88             # remember that nothing keeps you from still just adding your own:
89            
90             package My::Mocked::Package::Name;
91            
92             sub really_customized {} # skipping mock system
93              
94             package main; # remember to end your own package definition
95              
96             =head2 RUNNING
97              
98             mock_run(); # flow of calls from test planned, now prepare to run the test(s)
99              
100             eval {
101              
102             # package was already declared as loaded at mock_run()
103             # so code under test may freely try to 'use' it
104             use My::Mocked::Package::Name;
105              
106             code_under_test(); # dies on any unplanned call to a mocked package or sub
107              
108             mock_end(); # dies if any expected calls were not made and reports them
109             };
110              
111             is( $@, '', "code_under_test() executed according to prepared plan" );
112            
113             mock_clear(); # flush state, plan and mocks so you may plan another test call flow
114              
115             =head2 RECORDING
116              
117             To make it easier to start refactoring existing complicated legacy code,
118             C also provides preliminary sub call recording functionality:
119              
120             # load the packages used by code under test first
121             use My::Mocked::Package::Name;
122             use Other::Mocked::Package;
123              
124             # then declare them for mocking; this saves the original subs aside
125             mock_package( 'My::Mocked::Package::Name', 'Other::Mocked::Package' );
126              
127             # start recording
128             record_calls_from( 'Package::Under::Test' );
129            
130             # now calls to mocked packages will be made and recorded with their args and results
131             use Package::Under::Test;
132             Package::Under::Test->code_under_test();
133            
134             # generate code to serve as basis for your test run
135             print join ";\n", map { $_->name() } mock_plan()->list_calls();
136              
137             =head2 OBJECT ORIENTED USAGE
138              
139             C is actually object-oriented; default instance creation is hidden.
140             Usability of multiple simultaneous mock objects is hindered by Perl global package namespace.
141             Only one object may be used for recording, planning or running at a time.
142             A separate object can be used for each of those tasks simultaneously as long as they don't mock same packages.
143             Just do one thing at a time and C straight after to steer clear of any problems.
144              
145             use Test::CallFlow;
146            
147             my $flow = Test::CallFlow->new(
148             autoload_template => '' # do not declare AUTOLOAD, use explicit mock_call()s only
149             );
150              
151             $flow->mock_package( 'Just::Mocked' );
152             $flow->mock_call( 'Just::Mocked::new', 'Just::Mocked' )->result( bless( {}, 'Just::Mocked' ) );
153             $flow->mock_run;
154             print Just::Mocked->new;
155             $flow->mock_end;
156              
157             =cut
158              
159             BEGIN {
160 6     6   230 @ISA = qw(Exporter);
161 6         28 @EXPORT_OK =
162             qw(mock_package mock_object mock_run mock_end mock_reset mock_clear mock_call mock_plan arg_check arg_any record_calls_from);
163 6         12530 %EXPORT_TAGS = ( all => [@EXPORT_OK], );
164              
165             }
166              
167             =head1 PACKAGE PROPERTIES
168              
169             =over 4
170              
171             =item %Test::CallFlow::state
172              
173             Map of state names to state IDs. Used to refer to flow object states:
174              
175             unknown, record, plan, execute, failed, succeeded.
176              
177             =item @Test::CallFlow::state
178              
179             List of state names. Used to get printable name for state IDs.
180              
181             =item %Test::CallFlow::prototype
182              
183             Contains default values for instance properties.
184              
185             =item @Test::CallFlow::instance
186              
187             Array of created instances. Used by mocked methods to locate the related instance responsible of building and following the plan, ie. checking the call and providing right result to return.
188              
189             =back
190              
191             =cut
192              
193             my $i = 0;
194             %state = map { $_ => $i++ } @state =
195             qw(unknown record plan execute failed succeeded);
196              
197             =head1 INSTANCE PROPERTIES
198              
199             Default properties are defined in C<%Test::CallFlow::prototype>.
200             They may be specified as parameters for C
201             or environment variables with prefix C, such as C.
202              
203             Template texts below may contain C<#{variablename}> placeholders that will be
204             replaced by context-specific or C object property values.
205              
206             =head2 TEMPLATE PROPERTIES
207              
208             These may be useful for heavier customizations, although it'll probably be easier to just
209             define more hairy mock package parts straight in the test script.
210              
211             =over 4
212              
213             =item package_template
214              
215             Template text for mock package definitions. See code for contents.
216              
217             =over 8
218              
219             =item C<#{packagename}> placeholders will be replaced by name of package to mock.
220              
221             =item C<#{subs}> placeholders will be replaced by sub definitions.
222              
223             =back
224              
225             =item sub_template
226              
227             Template for code to put into mocked subs.
228              
229             =over 8
230              
231             =item C<#{packagename}> placeholders will be replaced by name of package to mock.
232              
233             =item C<#{subname}> placeholders will be replaced by name of sub to mock.
234              
235             =back
236              
237             =item autoload_template
238              
239             Template for code to put into mocked AUTOLOAD subs.
240              
241             =item package_definition_template
242              
243             Template for package definition at C.
244              
245             Default value contains redefinition warning suppression
246             and expects C<#{packagebody}> variable to contain actual mock package definition.
247              
248             =back
249              
250             =head2 INTERNAL PROPERTIES
251              
252             These are set and used at planning and runtime.
253              
254             =over 4
255              
256             =item state
257              
258             One of C<%Test::CallFlow::state> values.
259              
260             Default is C.
261             C sets state to C.
262             C sets it to C - or C if more calls were expected.
263             Failure in a mock call sets it to C.
264             C and C unconditionally set it back to C.
265              
266             =item id
267              
268             Index of this object in C<@Test::CallFlow::instances>.
269              
270             =item packages
271              
272             Contains data about packages and subs to mock gathered from calls in planning mode.
273              
274             =item plan
275              
276             Call execution plan as a C object containing C objects.
277              
278             =item record_calls_from
279              
280             Hash of package names created by C for checking which calls to record during recording.
281              
282             =back
283              
284             =head2 DEBUGGING PROPERTIES
285              
286             =over 4
287              
288             =item debug
289              
290             Controls debug information printing.
291             Class names in this string cause debugging info to be printed from them.
292             Options are: C, C, C, C. Derived from C<$ENV{DEBUG}>.
293              
294             =item debug_mock
295              
296             Controls whether to print debug info in this class.
297              
298             =back
299              
300             =head2 PACKAGE SAVING PROPERTIES
301              
302             Sometimes it might be nice to put the files into a temporary directory included in @INC,
303             or to keep them around for debugging or faster loading later.
304              
305             =over 4
306              
307             =item save
308              
309             Whether to save package definitions into files. Default is not to save.
310              
311             If set at construction, the temporary directory will be prepended to @INC so that
312             the mocks will load with C hiding any real implementations.
313              
314             =item basedir
315              
316             Base directory for saving packages. Default is system temporary directory.
317              
318             =item savedir
319              
320             Template for name of subdirectory inside basedir to contain saved package file hierarchy.
321             Default is 'perl-mock--'.
322              
323             =back
324              
325             =cut
326              
327             my %prototype = (
328              
329             'state' => $state{plan},
330              
331             # package instantiation stuff:
332              
333             'package_template' => '
334             package #{packagename};
335              
336             #{subs}
337              
338             1;
339             ',
340              
341             'autoload_template' => '
342             sub #{subname} {
343             @_ = ($Test::CallFlow::instances[#{id}], $#{packagename}::#{subname}, @_);
344             goto \&Test::CallFlow::mock_call
345             unless $#{packagename}::#{subname} eq \'#{packagename}::DESTROY\'
346             }
347             ',
348              
349             'sub_template' => '
350             sub #{subname} {
351             @_ = ($Test::CallFlow::instances[#{id}], \'#{packagename}::#{subname}\', @_);
352             goto \&Test::CallFlow::mock_call
353             }
354             ',
355              
356             # runtime package definition string
357             'package_definition_template' =>
358             "no warnings \'redefine\';\n#{packagebody}",
359              
360             # future Test::CallFlow::Package stuff:
361              
362             'save' => 0,
363             'basedir' => File::Spec->tmpdir,
364             'savedir' => "perl-test-callflow-$$-\#{id}",
365             );
366              
367             =head1 FUNCTIONS
368              
369             =head2 instance
370              
371             $mocker = Test::CallFlow::instance;
372              
373             Returns the first instance of this class created with given properties. Creates one if there isn't.
374              
375             This is called from each of the C subs exported with C<:all> tag so that
376             the library can easily be used procedurally.
377              
378             =cut
379              
380             sub instance {
381 32     32 1 82 my %properties = @_;
382              
383 32         71 for my $instance (@instances) {
384 0 0       0 return $instance
385             unless grep {
386 27 50       195 defined $properties{$_}
387             ? $instance->{$_} ne $properties{$_}
388             : defined $instance->{$_}
389             } keys %properties;
390             }
391              
392 5         48 Test::CallFlow->new(%properties);
393             }
394              
395             =head2 new
396              
397             my $mocker = Test::CallFlow->new( %properties );
398              
399             Returns a new C object with given properties.
400             Properties not given are taken from %Test::CallFlow::prototype.
401              
402             =cut
403              
404             sub new {
405 5     5 1 18 my ( $class, %self ) = @_;
406 5 50       20 $class = ref $class if ref $class;
407 5         24 $self{id} = @instances;
408              
409 5         45 for ( keys %prototype ) {
410 40 50       264 $self{$_} = exists $ENV{"mock_$_"} ? $ENV{"mock_$_"} : $prototype{$_}
    50          
411             unless exists $self{$_};
412             }
413              
414 5   50     101 $self{packages} ||= {};
415 5 50 33     73 $self{debug} = $ENV{DEBUG}
416             if not exists $self{debug} and exists $ENV{DEBUG};
417 5 50       20 $self{debug_mock} = $self{debug} =~ /\bMock\b/ if $self{debug};
418              
419 5 50       22 if ( $self{save} ) {
420 0         0 $self{savedir} =~ s/\#{(\w+)}/$self{$1}/g;
421 0         0 my $dir = File::Spec->catdir( $self{basedir}, $self{savedir} );
422 0 0       0 unshift @INC, $dir unless grep { $_ eq $dir } @INC;
  0         0  
423             }
424              
425 5         19 my $self = bless \%self, $class;
426 5         12 push @instances, $self;
427              
428 5 50       27 $recording = $self if $self{state} == $state{record};
429 5 50       26 $planning = $self if $self{state} == $state{plan};
430 5 50       37 $running = $self if $self{state} == $state{execute};
431              
432 5         60 return $self;
433             }
434              
435             =head2 record_calls_from
436              
437             record_calls_from( 'Package::Under::Test', 'Supplementary::Package::Under::Same::Test', );
438              
439             Starts recording calls from specified packages.
440              
441             Returns self.
442              
443             =cut
444              
445             sub record_calls_from {
446 1 50 33 1 1 24 my $self =
447             isa( $_[0], 'Test::CallFlow' ) ? shift : $recording
448             || $planning
449             || instance;
450 1 50 0     7 croak( "record_calls_from called in wrong state: ",
      33        
451             $state[ $self->{state} || 0 ] )
452             unless $self->{state} == $state{plan}
453             or $self->{state} == $state{record};
454              
455 1         6 $self->{record_calls_from}{$_} = 1 for @_;
456              
457 1         3 $self->{state} = $state{record};
458 1 50 50     9 $running = undef if ( $running || 0 ) == $self;
459 1 50 50     5 $planning = undef if ( $planning || 0 ) == $self;
460 1         3 $recording = $self;
461             }
462              
463             =head2 mock_run
464              
465             mock_run;
466              
467             End planning mocked calls and start executing tests.
468              
469             If compilation of a package fails, confesses its whole source.
470              
471             Returns self.
472              
473             =cut
474              
475             sub mock_run {
476 14 50 66 14 1 2517 my $self = isa( $_[0], 'Test::CallFlow' ) ? shift : $planning
477             || instance;
478 14         113 $self->save_mock_package($_)
479 14         44 for grep { !$self->{packages}{$_}{saved} }
  14         79  
480             sort keys %{ $self->{packages} };
481 14         36 for ( sort keys %{ $self->{packages} } ) {
  14         49  
482 14         80 $INC{ mock_package_filename($_) } = "mocked by $self";
483 14         78 my $plan = $self->embed( $self->{package_definition_template},
484             packagebody => $self->plan_mock_package($_) );
485 14     5   1844 eval $plan;
  5     3   38  
  5     4   8  
  5     4   822  
  3         152  
  3         67  
  3         892  
  4         32  
  4         8  
  4         1166  
  4         1419  
  4         11  
  4         612  
486 14 50       79 confess
487             "### FAILED MOCK PACKAGE DEFINITION ($@):\n$plan\n### END FAILED MOCK PACKAGE DEFINITION ($@)\n"
488             if $@;
489             }
490 14         144 $self->{state} = $state{execute};
491 14 100 100     105 $planning = undef if ( $planning || 0 ) == $self;
492 14         49 $running = $self;
493             }
494              
495             =head2 mock_end
496              
497             mock_end;
498              
499             End test execution.
500              
501             If any expected calls have not been made, dies with a list of unsatisfied calls.
502              
503             Returns self.
504              
505             =cut
506              
507             sub mock_end {
508 7 100 33 7 1 8186 my $self = isa( $_[0], 'Test::CallFlow' ) ? shift : $running
509             || instance;
510 7 50 50     61 $planning = undef if ( $planning || 0 ) == $self;
511 10 50 50     1242 $running = undef if ( $running || 0 ) == $self;
512 12 100 100     87 $recording = undef if ( $recording || 0 ) == $self;
513              
514 7 50 66     92 if ( $self->{state} != $state{execute}
515             and $self->{state} != $state{failed} )
516             {
517 1         4 $self->{state} = $state{failed};
518 1         34 confess "End mock in a bad state: ", $state[ $self->{state} ];
519             }
520              
521 7         42 my @unsatisfied = $self->{plan}->unsatisfied;
522 9 100       124 if (@unsatisfied) {
523 6         19 $self->{state} = $state{failed};
524 3         16 confess "End mock with ", scalar(@unsatisfied),
525             " calls remaining:\n" . join("\n"),
526 3         12 map { "\t" . $_->name } @unsatisfied;
527             }
528              
529 3         7 $self->{state} = $state{succeeded};
530              
531 3         9 $self;
532             }
533              
534             =head2 mock_clear
535              
536             mock_clear;
537              
538             Clears plan.
539             Restores any original subs covered by mocks.
540             Resets state unconditionally back to planning.
541              
542             Does not touch any other properties of mocked packages than subs mocked with C
543             (that's used implicitly during normal planning or recording).
544              
545             Does not currenctly remove any files created by requesting packages to be saved.
546             Maybe that should some day be a configurable option.
547              
548             Returns self.
549              
550             =cut
551              
552             sub mock_clear {
553 4 50 33 8 1 2611 my $self =
554             isa( $_[0], 'Test::CallFlow' ) ? shift : $running
555             || $planning
556             || $recording
557             || instance;
558              
559             # unmock mocked subs
560 6     6   184 no strict 'refs';
  6         14  
  6         832  
561 4 50       10 for my $package_name ( keys %{ $self->{packages} || {} } ) {
  4         24  
562 4         11 my $package = $self->{packages}{$package_name};
563 4   50     22 my $mocked_subs = $package->{subs} || {};
564 4   100     21 my $original_subs = $package->{original_subs} || {};
565 4         12 my $namespace = $package_name . '::';
566 4         9 for my $mocked_sub_name ( keys %{$mocked_subs} ) {
  4         19  
567 7         14 my $full_sub_name = $namespace . $mocked_sub_name;
568 7         11 my $original_sub = $original_subs->{$mocked_sub_name};
569 7 100       15 if ($original_sub) {
570 6     6   34 no warnings 'redefine';
  6         11  
  6         495  
571 1         2 *{$full_sub_name} = $original_sub;
  1         12  
572             } else {
573 6         13 undef *{$full_sub_name};
  6         91  
574             }
575             }
576             }
577 6     6   33 use strict 'refs';
  6         19  
  6         1883  
578              
579 4         12 delete $self->{record_calls_from};
580 4         15 delete $self->{packages};
581 4         74 delete $self->{plan};
582 4         11 $self->{state} = $state{plan};
583              
584 4 100 100     24 $running = undef if ( $running || 0 ) == $self;
585 4 50 50     38 $recording = undef if ( $recording || 0 ) == $self;
586              
587 4         11 $planning = $self;
588             }
589              
590             =head2 mock_reset
591              
592             mock_reset;
593              
594             Reset mock plan for re-run.
595              
596             =cut
597              
598             sub mock_reset {
599 8   33 9 1 12298 my $self = shift || instance;
600 8         48 $self->{plan}->reset;
601 8         21 delete $self->{record_calls_from};
602 8         30 $self->{state} = $state{plan};
603             }
604              
605             =head2 mock_package
606              
607             mock_package( 'Package::Name' );
608              
609             Declares package of given name to be mocked. Returns nothing.
610             Dies if the package declaration fails - ie. when invalid templates were specified for this mock object.
611              
612             C method gets declared to enable building plan by mock calls.
613              
614             =cut
615              
616             sub mock_package {
617 7 50 66 8 1 88 my $self = isa( $_[0], 'Test::CallFlow' ) ? shift : $planning
618             || instance;
619 7 50       28 my $name = shift or confess "Can't mock a package without a name";
620 7 50       70 return if exists $self->{packages}{$name};
621              
622 7         28 $self->{packages}{$name} = {@_};
623 7 50       54 unless ( exists $self->{packages}{$name}{subs}{AUTOLOAD} ) {
624 7         34 $self->mock_sub( $name, 'AUTOLOAD', $self->{autoload_template} );
625             }
626              
627 6     6   38 no strict 'refs';
  6         12  
  6         818  
628 7         20 my $namespace_name = $name . '::';
629 7         10 my %namespace = %{$namespace_name};
  7         63  
630 7         27 for my $sub_name ( keys %namespace ) {
631 15 100       18 my $sub = *{ $namespace{$sub_name} }{CODE} or next;
  15         70  
632 1   33     17 $self->{packages}{$name}{original_subs}{$sub_name} ||= $sub;
633 1         3 $self->mock_sub( $name, $sub_name );
634             }
635 6     6   40 use strict 'refs';
  6         13  
  6         21577  
636              
637 7         120 my $plan = $self->embed( $self->{package_definition_template},
638             packagebody => $self->plan_mock_package($name) );
639              
640 7 50       36 warn $plan if $self->{debug_mock};
641 7     5   642 eval $plan;
  5         48  
  5         9  
  5         619  
642 7 50       46 die $@ if $@;
643             }
644              
645             =head2 mock_object
646              
647             my $mocked = mock_object( 'Package::Name' );
648             my $mocked_scalar = mock_object( 'Scalar::Blessed', "bless this scalar" );
649              
650             Returns an object of given mocked package. Declares that package for mocking if necessary.
651              
652             =cut
653              
654             sub mock_object {
655 4 50 33 7 1 114 my $self = isa( $_[0], 'Test::CallFlow' ) ? shift : $planning
656             || instance;
657 4         12 my $name = shift;
658 4 50       48 my $object = @_ ? shift : {};
659 4         18 mock_package($name);
660              
661 4         18 bless $object, $name;
662             }
663              
664             =head2 mock_sub
665              
666             my $props_ref = mock_sub( 'Package::Name', 'sub_name', 'sub #{subname} { warn "#{subname}(@_) called" }' );
667              
668             Declares given package to contain given sub such that it will actually execute Test::CallFlow::mock_call -
669             or alternatively given template text.
670              
671             Template may contain placeholders marked as #{name} to be substituted with values
672             of any property of the C object or
673              
674             =over 4
675              
676             =item subname
677              
678             Name of sub being defined
679              
680             =item packagename
681              
682             Name of package being defined
683              
684             =back
685              
686             =cut
687              
688             sub mock_sub {
689 19 50 0 19 1 95 my $self = isa( $_[0], 'Test::CallFlow' ) ? shift : $planning
690             || instance;
691 19         51 my ( $package, $sub, $code ) = @_;
692 19 50       62 $self->mock_package($package)
693             unless exists $self->{packages}{$package};
694 19         53 delete $self->{packages}{$package}{saved};
695 19         67 $self->{packages}{$package}{subs}{$sub} =
696             $code; # undef ok, default sub_template will be used
697             }
698              
699             =head2 mock_call
700              
701             mock_call( 'Mocked::Package::sub_name', @args );
702              
703             Called from mocked packages.
704              
705             During plan buildup, adds calls to mock call plan list.
706              
707             During test execution, tries to find a planned mock call matching given call.
708             Returns planned value. Dies on mismatch.
709              
710             During recording calls the original method. If caller is a record candidate, records the call and result.
711              
712             =cut
713              
714             sub mock_call {
715 49 50 0 49 1 279 my $self =
716             isa( $_[0], 'Test::CallFlow' ) ? $_[0] : $planning
717             || $running
718             || instance;
719              
720 49 100 50     637 my $target = {
      50        
721             $state{plan} => \&plan_mock_call,
722             $state{execute} => \&execute_mock_call,
723             $state{record} => \&record_mock_call
724             }->{ $self->{state} || 0 }
725             or croak "Mock call in a bad state: ", $state[ $self->{state} || 0 ];
726 48 50       181 warn "mock_call in $state[$self->{state}] state" if $self->{debug_mock};
727              
728 48         141 goto $target;
729             }
730              
731             =head2 mock_plan
732              
733             Returns reference to the Test::CallFlow::Plan object.
734              
735             =cut
736              
737             sub mock_plan {
738 1 50 0 1 1 545 my $self =
739             isa( $_[0], 'Test::CallFlow' ) ? $_[0] : $recording
740             || $planning
741             || $running
742             || instance;
743              
744 1         6 $self->{plan};
745             }
746              
747             =head2 arg_check
748              
749             $mocked->method( arg_check(qr/../), arg_check( sub { $_[2]->[$_[1]] < 5 }, 0, 99 ) );
750              
751             Instantiates an object of correct subclass of Test::CallFlow::ArgCheck for given test; either Regexp or Code reference.
752              
753             Arguments are
754              
755             =over 4
756              
757             =item 1. The test: a regular expression, code reference or scalar
758              
759             =item 2. minimum number of arguments to match: 0 for optional
760              
761             =item 3. maximum number of arguments to match.
762              
763             =back
764              
765             =cut
766              
767             sub arg_check {
768 4     4 1 25 my @args = qw(test min max);
769 4         8 my %checker = map { shift(@args), $_ } @_;
  6         18  
770 4 100 50     31 $checker{min} ||= 1 unless defined $checker{min};
771 4   50     31 $checker{max} ||= $checker{min} || 1;
      66        
772 4   50     31 my $class = "Test::CallFlow::ArgCheck::"
773             . ucfirst( lc( ref( $checker{test} ) || 'equals' ) );
774 4         4 my $checker;
775 4         209 eval "use $class; \$checker = $class->new(\%checker)";
776 4 50       14 confess $@ if $@;
777 4         80 $checker;
778             }
779              
780             =head2 arg_any
781              
782             $mocked->method( arg_any, 'X', arg_any( 0, -1 ) );
783              
784             Returns an argument checker that passes any arguments.
785             Optional arguments specify minimum (default 1) and maximum (default same as minimum)
786             possible number of arguments to pass.
787              
788             =cut
789              
790             sub arg_any {
791 2     2 1 7 my %args;
792 2 50 33     38 $args{min} = shift if @_ and $_[0] =~ /^\d+$/;
793 2 50 33     25 $args{max} = shift if @_ and $_[0] =~ /^\d+$/;
794 2         29 Test::CallFlow::ArgCheck::Any->new( %args, @_ );
795             }
796              
797             =head1 INTERNAL METHODS
798              
799             These are not exported with C<:all>.
800              
801             =head2 save_mock_package
802              
803             Saves given package if saving is not disabled for it and enabled for it or by default.
804             Location is basedir/savedir/containingpackage/packagename.pm.
805              
806             Dies on I/O failures.
807              
808             =cut
809              
810             sub save_mock_package {
811 14 50 0 14 1 100 my $self = isa( $_[0], 'Test::CallFlow' ) ? shift : $planning
812             || instance;
813 14         99 my ($package_name) = shift;
814              
815             # package must exist and be set to be saved, not be set to not save
816             return
817 14 50 33     184 unless exists $self->{packages}{$package_name}
    50          
818             and exists $self->{packages}{$package_name}{save}
819             ? $self->{packages}{$package_name}{save}
820             : $self->{save};
821              
822 0         0 my $plan = $self->plan_mock_package( $package_name, @_ );
823              
824 0         0 my $dir = $self->{basedir};
825 0         0 my @dir = ( $self->{savedir}, split /::/, $package_name );
826 0         0 my $filename = pop(@dir) . ".pm";
827 0         0 for (@dir) {
828 0         0 $dir = File::Spec->catdir( $dir, $_ );
829 0 0       0 mkdir $dir unless -d $dir;
830             }
831 0         0 my $fullfile = File::Spec->catdir( $dir, $filename );
832 0 0       0 warn "Save '$fullfile'" if $self->{debug_mock};
833 0 0       0 my $fh = IO::File->open( $fullfile, 'w' ) or die $!;
834 0         0 $fh->print($plan);
835 0 0       0 $fh->close or die $!;
836 0         0 $self->{packages}{$package_name}{saved} = 1;
837             }
838              
839             =head2 plan_mock_package
840              
841             my $package_definition = plan_mock_package( 'My::Mocked::Package::Name' );
842              
843             Returns a string containing the perl code for a package with mock versions of all methods called so far.
844              
845             =cut
846              
847             sub plan_mock_package {
848 21 50   21 1 105 my $self = isa( $_[0], 'Test::CallFlow' ) ? shift : instance;
849 21         38 my ($package_name) = @_;
850 21 50       69 return unless defined $self->{packages}{$package_name};
851 21   50     89 my $subs = $self->{packages}{$package_name}{subs} || {};
852              
853 58   66     466 $self->embed(
854             $self->{package_template} || $self->{sub_template},
855             packagename => $package_name,
856             subs => join '',
857             map {
858 21   33     321 $self->embed(
859             $subs->{$_} || $self->{sub_template},
860             packagename => $package_name,
861             subname => $_,
862             )
863             } sort grep /^\w+$/,
864             keys %$subs
865             );
866             }
867              
868             =head2 embed
869              
870             my $text = $mocker->embed( 'sub #{subname} { "mocked sub of #{packagename}" }', subname => 'my_mock' );
871              
872             Embeds given values and object properties as referred by placeholders in given text.
873              
874             Does not recurse indefinitely, but gives silently up after 15 recursions.
875              
876             =cut
877              
878             sub embed {
879 100 50 0 100 1 778 my $self = isa( $_[0], 'Test::CallFlow' ) ? shift : $planning
880             || instance;
881 100         123 my $text = shift;
882 100         1495 my (%embeddable) = ( %$self, @_ );
883 100         1881 my $embeddable_keys = join '|', keys %embeddable;
884 100         215 my $depth = 16;
885 100   66     11547 1 while --$depth and $text =~ s/#{($embeddable_keys)}/$embeddable{$1}/g;
886 100         1428 $text;
887             }
888              
889             =head2 mock_package_filename
890              
891             my $filename = mock_package_filename( 'My::Mocked::Package::Name' );
892              
893             Returns relative path and filename combination string for given package name.
894              
895             =cut
896              
897             sub mock_package_filename {
898 14 50 66 14 1 149 my $self = isa( $_[0], 'Test::CallFlow' ) ? shift : $planning
899             || instance;
900 14         29 my ($package_name) = shift;
901              
902 14         296 File::Spec->catdir( split /::/, $package_name ) . '.pm';
903             }
904              
905             =head2 plan_mock_call
906              
907             $mocker->plan_mock_call( 'Mocked::Package::sub_name', @args );
908              
909             Adds a call with given package::sub name and arguments to call plan.
910              
911             =cut
912              
913             sub plan_mock_call {
914 12     12 1 22 my $self = shift;
915 12 50       41 my $sub = shift or confess "No sub";
916 12 100       30 unless ( ref $sub ) {
917 11         67 my ( $package, $method ) = $sub =~ /(.+)::([^:]+)$/;
918 11 50 33     182 $self->mock_sub( $package, $method )
919             unless $self->{packages}{$package}
920             and $self->{packages}{$package}{subs}{$sub};
921             }
922 12 50 50     153 my $call_plan =
923             Test::CallFlow::Call->new(
924             args => [ $sub, @_ ],
925             ( $self->{debug} || '' ) =~ /\bCall\b/
926             ? ( debug => $self->{debug} )
927             : ()
928             );
929 12 50 50     145 $self->{plan} ||=
      66        
930             Test::CallFlow::Plan->new(
931             ( $self->{debug} || '' ) =~ /\bPlan\b/
932             ? ( debug => $self->{debug} )
933             : ()
934             );
935 12         52 $self->{plan}->add_call($call_plan);
936 12 50       44 warn "Planned call $sub(@_)" if $self->{debug_mock};
937              
938 12         90 $call_plan;
939             }
940              
941             =head2 execute_mock_call
942              
943             Called from C when running tests against plan.
944              
945             Returns result from planned mock call matching given executed call if one exists.
946              
947             =cut
948              
949             sub execute_mock_call {
950 36     36 1 67 my $self = shift;
951 36         59 my @result;
952 36         51 eval { @result = $self->{plan}->call(@_); };
  36         178  
953 36 100       919 if ($@) {
954 10         31 $self->{state} = $state{failed};
955 10         59 die $@;
956             }
957 26 100       124 wantarray ? @result : $result[0];
958             }
959              
960             =head2 record_mock_call
961              
962             Called from C when recording calls.
963              
964             Returns result of call to original method.
965              
966             =cut
967              
968             sub record_mock_call {
969 1     1 1 2 my $self = shift;
970 1 50       4 my $sub = shift or confess "No sub";
971 1         7 my ( $package_name, $sub_name ) = $sub =~ /(.+)::([^:]+)$/;
972              
973 1 50       5 my $package = $self->{packages}{$package_name}
974             or confess "No package '$package_name' for $sub(@_)";
975              
976 1 50       5 my $orig = $package->{original_subs}{$sub_name}
977             or confess "No such original sub $sub(@_)";
978              
979 1 50       6 my @result = wantarray ? ( $orig->(@_) ) : ( scalar $orig->(@_) );
980              
981 1         15 my ( $caller_package, $caller_file, $caller_line ) = caller(0);
982 1 50       5 if ( $self->{record_calls_from}{$caller_package} ) {
983 1         6 my $caller_sub = ( caller 1 )[3];
984 1         5 my $called = "$caller_sub at $caller_file line $caller_line";
985 1         5 $self->plan_mock_call( $sub, @_ )->result(@result)
986             ->called_from($called);
987             }
988              
989 1 50       8 wantarray ? @result : $result[0];
990             }
991              
992             =head1 TODO
993              
994             =over 4
995              
996             =item * MockCommand
997              
998             Integration to cover external command calls.
999              
1000             =item * Tied Variables
1001              
1002             Provide easy methods for recording, restricting and testing data access.
1003              
1004             =item * Test::CallFlow::Package
1005              
1006             Would allow for neat stuff like
1007              
1008             mock_package( 'Bar' )->vars( ISA => [ 'Foo' ], VERSION => 0.01 );
1009              
1010             =item * ArgCheck::Hash
1011              
1012             ArgChecker for deep structure comparison. Add also C.
1013              
1014             =item * ArgCheck::Array
1015              
1016             ArgChecker for a match in a list; used as C.
1017              
1018             =item * Ref Checking
1019              
1020             Document the fact that Regexp /^Type::Name=/ may be used for reference type checks.
1021              
1022             =back
1023              
1024             =head1 AUTHOR
1025              
1026             Kalle Hallivuori, C<< >>
1027              
1028             =head1 BUGS
1029              
1030             Please report any bugs or feature requests to C, or through
1031             the web interface at L. I will be notified, and then you'll
1032             automatically be notified of progress on your bug as I make changes.
1033              
1034              
1035             =head1 SUPPORT
1036              
1037             You can find documentation for this module with the perldoc command.
1038              
1039             perldoc Test::CallFlow
1040              
1041              
1042             You can also look for information at:
1043              
1044             =over 4
1045              
1046             =item * RT: CPAN's request tracker
1047              
1048             L
1049              
1050             =item * AnnoCPAN: Annotated CPAN documentation
1051              
1052             L
1053              
1054             =item * CPAN Ratings
1055              
1056             L
1057              
1058             =item * Search CPAN
1059              
1060             L
1061              
1062             =back
1063              
1064             =head1 SEE ALSO
1065              
1066             =head2 ALTERNATIVES
1067              
1068             Test::CallFlow provides a very simple way to plan mocks.
1069             Other solutions are available, each with their strong points.
1070              
1071             =over 4
1072              
1073             =item * Test::MockClass
1074              
1075             Very clearly named methods are used to create and control mocks.
1076             Supports explicit call order. Does not provide unified flexible argument checking.
1077             Call tracking can be disabled.
1078              
1079             =item * Test::MockObject
1080              
1081             Collects calls made so that you can check them in your own code afterwards.
1082              
1083             =item * Test::MockModule
1084              
1085             You provide the code for each mocked method separately. No flow checks.
1086             Original methods are remembered and can be restored later.
1087              
1088             =item * Test::MockCommand
1089              
1090             Mock external commands that your program calls.
1091              
1092             =back
1093              
1094             =head2 SUPPLEMENTARY MODULES
1095              
1096             =over 4
1097              
1098             =item * Test::CallFlow::Plan
1099              
1100             A structure of calls the code under test should make.
1101              
1102             =item * Test::CallFlow::Call
1103              
1104             A single call that the code under test might make.
1105              
1106             =item * Test::CallFlow::ArgCheck
1107              
1108             Checkers for arguments to mocked function calls.
1109              
1110             =item * Test::CallFlow::ArgCheck::Equals
1111              
1112             Pass arguments that match given string or undef.
1113              
1114             =item * Test::CallFlow::ArgCheck::Code
1115              
1116             Pass arguments that given method returns true for.
1117              
1118             =item * Test::CallFlow::ArgCheck::Regexp
1119              
1120             Pass arguments that are defined and match given regexp.
1121              
1122             =item * Test::CallFlow::ArgCheck::Any
1123              
1124             Pass any arguments.
1125              
1126             =back
1127              
1128             =head1 ACKNOWLEDGEMENTS
1129              
1130             =over 4
1131              
1132             =item * chromatic, author of Test::MockObject
1133              
1134             Perl namespace management details I got from his code.
1135              
1136             =item * Simon Flack, author of Test::MockModule
1137              
1138             Perl namespace management details I got from his code.
1139              
1140             =back
1141              
1142             =head1 COPYRIGHT & LICENSE
1143              
1144             Copyright 2008 Kalle Hallivuori, all rights reserved.
1145              
1146             This program is free software; you can redistribute it and/or modify it
1147             under the same terms as Perl itself.
1148              
1149             =cut
1150              
1151             1; # End of Test::CallFlow