Author image Kalle Hallivuori


Test::CallFlow - trivial planning of sub call flows for fast unit test writing.


Version 0.03


Mock packages for planning expected interactions in tests:

    use Test::CallFlow qw(:all);

    my $mocked = mock_object( 'My::Mocked::Package::Name' );
    $mocked->my_method( arg_any(0,9) )->result( 'return value' );


    die "test did not return right value"
      if $mocked->my_method( 'any', 'arguments' ) ne 'return value';



Test::CallFlow functions are used here in a procedural manner because straightforward test scripts are seen as primary use case. As well you may create objects with new() and use the provided functions as object methods.


    use Test::More plan_tests => 1;
    use Test::CallFlow qw(:all);

    # just mock a package
    mock_package( 'Just::Mocked' );

    # mock a package and make an object of it
    my $mocked = mock_object(
        'My::Mocked::Package::Name',          # must specify package name
        { 'optional' => 'content' } );        # may specify what to bless


    Just::Mocked->new()                       # no arguments
                ->result( $mocked );          # return the mock object

    my $get_call =                            # refer to this Test::CallFlow::Call object
        $mocked->get( "FieldX" )              # one equal string argument
             ->result( 1, 2, 3 )              # return array ( 1, 2, 3 ) on first call
             ->result( 4, 5, 6 )              # return array ( 4, 5, 6 ) on second call
             ->result( 7, 8, 9 )              # return array ( 7, 8, 9 ) on any subsequent calls
             ->min(0)                         # this call is optional
             ->max(9)                         # this call can be made at most 9 times
             ->anytime;                       # may be called at this step or any time later

    $mocked->set( arg_check( qr/^Field/ ),    # first argument matching regular expression
                  arg_any( 1, 99 ) );         # 1-99 arguments with any values
                                              # return nothing (undef or empty array)

    $mocked->save( arg_check( \&ok_file ) )   # use own code to check argument
             ->end( $get_call );              # end scope: $get_call can be made no more

    # if you wish to use parts of the real package unmocked as is,
    # load it after planning but before running:
    use My::Mocked::Package::Name;
    # remember that nothing keeps you from still just adding your own:
    package My::Mocked::Package::Name;
    sub really_customized {} # skipping mock system

    package main; # remember to end your own package definition


    mock_run();  # flow of calls from test planned, now prepare to run the test(s)

    eval {

      # package was already declared as loaded at mock_run()
      # so code under test may freely try to 'use' it
      use My::Mocked::Package::Name;

      code_under_test();  # dies on any unplanned call to a mocked package or sub

      mock_end(); # dies if any expected calls were not made and reports them

    is( $@, '', "code_under_test() executed according to prepared plan" );
    mock_clear(); # flush state, plan and mocks so you may plan another test call flow


To make it easier to start refactoring existing complicated legacy code, Test::CallFlow also provides preliminary sub call recording functionality:

    # load the packages used by code under test first
    use My::Mocked::Package::Name;
    use Other::Mocked::Package;

    # then declare them for mocking; this saves the original subs aside
    mock_package( 'My::Mocked::Package::Name', 'Other::Mocked::Package' );

    # start recording
    record_calls_from( 'Package::Under::Test' );
    # now calls to mocked packages will be made and recorded with their args and results
    use Package::Under::Test;
    # generate code to serve as basis for your test run
    print join ";\n", map { $_->name() } mock_plan()->list_calls();


Test::CallFlow is actually object-oriented; default instance creation is hidden. Usability of multiple simultaneous mock objects is hindered by Perl global package namespace. Only one object may be used for recording, planning or running at a time. A separate object can be used for each of those tasks simultaneously as long as they don't mock same packages. Just do one thing at a time and mock_clear() straight after to steer clear of any problems.

  use Test::CallFlow;
  my $flow = Test::CallFlow->new(
        autoload_template => '' # do not declare AUTOLOAD, use explicit mock_call()s only

  $flow->mock_package( 'Just::Mocked' );
  $flow->mock_call( 'Just::Mocked::new', 'Just::Mocked' )->result( bless( {}, 'Just::Mocked' ) );
  print Just::Mocked->new;



Map of state names to state IDs. Used to refer to flow object states:

  unknown, record, plan, execute, failed, succeeded.

List of state names. Used to get printable name for state IDs.


Contains default values for instance properties.


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.


Default properties are defined in %Test::CallFlow::prototype. They may be specified as parameters for new or environment variables with prefix mock_, such as mock_save.

Template texts below may contain #{variablename} placeholders that will be replaced by context-specific or Test::CallFlow object property values.


These may be useful for heavier customizations, although it'll probably be easier to just define more hairy mock package parts straight in the test script.


Template text for mock package definitions. See code for contents.

#{packagename} placeholders will be replaced by name of package to mock.
#{subs} placeholders will be replaced by sub definitions.

Template for code to put into mocked subs.

#{packagename} placeholders will be replaced by name of package to mock.
#{subname} placeholders will be replaced by name of sub to mock.

Template for code to put into mocked AUTOLOAD subs.


Template for package definition at mock_run.

Default value contains redefinition warning suppression and expects #{packagebody} variable to contain actual mock package definition.


These are set and used at planning and runtime.


One of %Test::CallFlow::state values.

Default is plan. mock_run() sets state to execute. mock_end sets it to succeeded - or failed if more calls were expected. Failure in a mock call sets it to failed. mock_clear and mock_reset unconditionally set it back to plan.


Index of this object in @Test::CallFlow::instances.


Contains data about packages and subs to mock gathered from calls in planning mode.


Call execution plan as a Test::CallFlow::Plan object containing Test::CallFlow::Call objects.


Hash of package names created by record_calls_from() for checking which calls to record during recording.



Controls debug information printing. Class names in this string cause debugging info to be printed from them. Options are: Mock, Plan, Call, ArgCheck. Derived from $ENV{DEBUG}.


Controls whether to print debug info in this class.


Sometimes it might be nice to put the files into a temporary directory included in @INC, or to keep them around for debugging or faster loading later.


Whether to save package definitions into files. Default is not to save.

If set at construction, the temporary directory will be prepended to @INC so that the mocks will load with use hiding any real implementations.


Base directory for saving packages. Default is system temporary directory.


Template for name of subdirectory inside basedir to contain saved package file hierarchy. Default is 'perl-mock-<process-id>-<mock-instance-number>'.



  $mocker = Test::CallFlow::instance;

Returns the first instance of this class created with given properties. Creates one if there isn't.

This is called from each of the mock_ subs exported with :all tag so that the library can easily be used procedurally.


        my $mocker = Test::CallFlow->new( %properties );

Returns a new Test::CallFlow object with given properties. Properties not given are taken from %Test::CallFlow::prototype.


   record_calls_from( 'Package::Under::Test', 'Supplementary::Package::Under::Same::Test', );

Starts recording calls from specified packages.

Returns self.



End planning mocked calls and start executing tests.

If compilation of a package fails, confesses its whole source.

Returns self.



End test execution.

If any expected calls have not been made, dies with a list of unsatisfied calls.

Returns self.



Clears plan. Restores any original subs covered by mocks. Resets state unconditionally back to planning.

Does not touch any other properties of mocked packages than subs mocked with mock_sub() (that's used implicitly during normal planning or recording).

Does not currenctly remove any files created by requesting packages to be saved. Maybe that should some day be a configurable option.

Returns self.



Reset mock plan for re-run.


  mock_package( 'Package::Name' );

Declares package of given name to be mocked. Returns nothing. Dies if the package declaration fails - ie. when invalid templates were specified for this mock object.

AUTOLOAD method gets declared to enable building plan by mock calls.


  my $mocked = mock_object( 'Package::Name' );
  my $mocked_scalar = mock_object( 'Scalar::Blessed', "bless this scalar" );

Returns an object of given mocked package. Declares that package for mocking if necessary.


  my $props_ref = mock_sub( 'Package::Name', 'sub_name', 'sub #{subname} { warn "#{subname}(@_) called" }' );

Declares given package to contain given sub such that it will actually execute Test::CallFlow::mock_call - or alternatively given template text.

Template may contain placeholders marked as #{name} to be substituted with values of any property of the Test::CallFlow object or


Name of sub being defined


Name of package being defined


   mock_call( 'Mocked::Package::sub_name', @args );

Called from mocked packages.

During plan buildup, adds calls to mock call plan list.

During test execution, tries to find a planned mock call matching given call. Returns planned value. Dies on mismatch.

During recording calls the original method. If caller is a record candidate, records the call and result.


Returns reference to the Test::CallFlow::Plan object.


  $mocked->method( arg_check(qr/../), arg_check( sub { $_[2]->[$_[1]] < 5 }, 0, 99 ) );

Instantiates an object of correct subclass of Test::CallFlow::ArgCheck for given test; either Regexp or Code reference.

Arguments are

1. The test: a regular expression, code reference or scalar
2. minimum number of arguments to match: 0 for optional
3. maximum number of arguments to match.


  $mocked->method( arg_any, 'X', arg_any( 0, -1 ) );

Returns an argument checker that passes any arguments. Optional arguments specify minimum (default 1) and maximum (default same as minimum) possible number of arguments to pass.


These are not exported with :all.


Saves given package if saving is not disabled for it and enabled for it or by default. Location is basedir/savedir/containingpackage/

Dies on I/O failures.


  my $package_definition = plan_mock_package( 'My::Mocked::Package::Name' );

Returns a string containing the perl code for a package with mock versions of all methods called so far.


  my $text = $mocker->embed( 'sub #{subname} { "mocked sub of #{packagename}" }', subname => 'my_mock' );

Embeds given values and object properties as referred by placeholders in given text.

Does not recurse indefinitely, but gives silently up after 15 recursions.


  my $filename = mock_package_filename( 'My::Mocked::Package::Name' );

Returns relative path and filename combination string for given package name.


  $mocker->plan_mock_call( 'Mocked::Package::sub_name', @args );

Adds a call with given package::sub name and arguments to call plan.


Called from mock_call when running tests against plan.

Returns result from planned mock call matching given executed call if one exists.


Called from mock_call when recording calls.

Returns result of call to original method.


  • MockCommand

    Integration to cover external command calls.

  • Tied Variables

    Provide easy methods for recording, restricting and testing data access.

  • Test::CallFlow::Package

    Would allow for neat stuff like

      mock_package( 'Bar' )->vars( ISA => [ 'Foo' ], VERSION => 0.01 );
  • ArgCheck::Hash

    ArgChecker for deep structure comparison. Add also arg_deep.

  • ArgCheck::Array

    ArgChecker for a match in a list; used as arg_check( \@in ).

  • Ref Checking

    Document the fact that Regexp /^Type::Name=/ may be used for reference type checks.


Kalle Hallivuori, <kato at>


Please report any bugs or feature requests to bug-test-callflow at, or through the web interface at I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.


You can find documentation for this module with the perldoc command.

    perldoc Test::CallFlow

You can also look for information at:



Test::CallFlow provides a very simple way to plan mocks. Other solutions are available, each with their strong points.

  • Test::MockClass

    Very clearly named methods are used to create and control mocks. Supports explicit call order. Does not provide unified flexible argument checking. Call tracking can be disabled.

  • Test::MockObject

    Collects calls made so that you can check them in your own code afterwards.

  • Test::MockModule

    You provide the code for each mocked method separately. No flow checks. Original methods are remembered and can be restored later.

  • Test::MockCommand

    Mock external commands that your program calls.


  • Test::CallFlow::Plan

    A structure of calls the code under test should make.

  • Test::CallFlow::Call

    A single call that the code under test might make.

  • Test::CallFlow::ArgCheck

    Checkers for arguments to mocked function calls.

  • Test::CallFlow::ArgCheck::Equals

    Pass arguments that match given string or undef.

  • Test::CallFlow::ArgCheck::Code

    Pass arguments that given method returns true for.

  • Test::CallFlow::ArgCheck::Regexp

    Pass arguments that are defined and match given regexp.

  • Test::CallFlow::ArgCheck::Any

    Pass any arguments.


  • chromatic, author of Test::MockObject

    Perl namespace management details I got from his code.

  • Simon Flack, author of Test::MockModule

    Perl namespace management details I got from his code.


Copyright 2008 Kalle Hallivuori, all rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.