[Melbourne-pm] Testing: stub modules and Test::More.

Steve Sabljak steve at sabljak.org
Mon Mar 5 04:39:18 PST 2007


Hi Daniel,

I think MockModule only overrides functions in existing modules, it
doesn't take any measures to avoid loading the module.
Kirrily mentioned Test::MockObject. This does not need to load an
existing module at all in order to fake it. You just need to make sure
the MockObject code runs before your module is 'used' in the test, so
put it in a BEGIN block. If you're using non-oo modules you'll need
your mocked module to provide an import function to export the mocked
modules interface.
Should work with fully qualified functions and exported ones.
Here's an example...

------ start baz.t -----
#!/usr/bin/perl

use strict;
use warnings;

use Test::More tests => 2;
use Test::MockObject;

BEGIN {
    my $foo = sub { return 'Mock::foo' };
    my $bar = sub { return 'Mock::bar' };

    my $mock = Test::MockObject->new();

    $mock->fake_module(
        'MyA',
        import => sub {
            my $pkg = shift;
            my $callpkg = caller(0);
            {
                no strict 'refs';
                *{"$callpkg\::foo"} = $foo;
                *{"$callpkg\::bar"} = $bar;
            }
        },
        foo => $foo,
        bar => $bar,
    );

    use_ok('MyB');
}

is(baz(), 'Mock::foo|Mock::bar', 'baz returned value based on mocked values');

----- end baz.t -----

----- start MyB.pm -----
package MyB;

use MyA;

use Exporter;

use base qw( Exporter );

our @EXPORT = qw( baz );

sub baz {
    my $foo = foo();
    my $bar = MyA::bar();
    return $foo . '|' . $bar;
}

1;
----- end MyB.pm -----

Hope this helps.

cheers,
Steve


More information about the Melbourne-pm mailing list