Temporarily replaces one or more subroutines in the mocked module. A subroutine
can be mocked with a code reference or a scalar. A scalar will be recast as a
subroutine that returns the scalar.
The following statements are equivalent:
$module->mock(purge => 'purged');
$module->mock(purge => sub { return 'purged'});
When dealing with references, things behave slightly differently. The following
statements are NOT equivalent:
# Returns the same arrayref each time, with the localtime() at time of mocking
$module->mock(updated => [localtime()]);
# Returns a new arrayref each time, with up-to-date localtime() value
$module->mock(updated => sub { return [localtime()]});
The following statements are in fact equivalent:
my $array_ref = [localtime()]
$module->mock(updated => $array_ref)
$module->mock(updated => sub { return $array_ref });
However, undef
is a special case. If you mock a subroutine with undef
it
will install an empty subroutine
$module->mock(purge => undef);
$module->mock(purge => sub { });
rather than a subroutine that returns undef
:
$module->mock(purge => sub { undef });
You can call mock()
for the same subroutine many times, but when you call
unmock()
, the original subroutine is restored (not the last mocked
instance).
MOCKING + EXPORT
If you are trying to mock a subroutine exported from another module, this may
not behave as you initially would expect, since Test::MockModule is only mocking
at the target module, not anything importing that module. If you mock the local
package, or use a fully qualified function name, you will get the behavior you
desire:
use Test::MockModule;
use Test::More;
use POSIX qw/strftime/;
my $posix = Test::MockModule->new("POSIX");
$posix->mock("strftime", "Yesterday");
is strftime("%D", localtime(time)), "Yesterday", "`strftime` was mocked successfully"; # Fails
is POSIX::strftime("%D", localtime(time)), "Yesterday", "`strftime` was mocked successfully"; # Succeeds
my $main = Test::MockModule->new("main", no_auto => 1);
$main->mock("strftime", "today");
is strftime("%D", localtime(time)), "today", "`strftime` was mocked successfully"; # Succeeds
If you are trying to mock a subroutine that was exported into a module that you're
trying to test, rather than mocking the subroutine in its originating module,
you can instead mock it in the module you are testing:
package MyModule;
use POSIX qw/strftime/;
sub minus_twentyfour
{
return strftime("%a, %b %d, %Y", localtime(time - 86400));
}
package main;
use Test::More;
use Test::MockModule;
my $posix = Test::MockModule->new("POSIX");
$posix->mock("strftime", "Yesterday");
is MyModule::minus_twentyfour(), "Yesterday", "`minus-twentyfour` got mocked"; # fails
my $mymodule = Test::MockModule->new("MyModule", no_auto => 1);
$mymodule->mock("strftime", "Yesterday");
is MyModule::minus_twentyfour(), "Yesterday", "`minus-twentyfour` got mocked"; # succeeds