Test2::Mock(3)
π¦ Test2::Mock π¦
okay so first things first: this page is Test2::Mock, and it comes to you straight from the User Contributed Perl Documentation section of the manpages β¨. She's a Perl module, she's here to help you fake it till you make it, and she's genuinely iconic for it.
πΈ NAME πΈ
Test2::Mock β a module for managing mocked classes and instances π
π DESCRIPTION π
so here's the whole vibe, bestie: this module lets you add and override methods for any package, temporarily π«Ά. Like, you borrow someone's class, dress it up in a little costume, and everybody plays along.
and the best part? when the instance is destroyed, it will restore the package to its original state π₯. so it's fully reversible. it's giving "borrowed your hoodie and gave it back washed" energy. no cap.
β¨ SYNOPSIS β¨
okay here's what it actually looks like in the wild, copy-paste ready π
use Test2::Mock;
use MyClass;
my $mock = Test2::Mock->new(
track => $BOOL, # enable call tracking if desired
class => 'MyClass',
override => [
name => sub { 'fred' },
...
],
add => [
is_mocked => sub { 1 }
...
],
...
);
# Unmock the 'name' sub
$mock->restore('name');
...
$mock = undef; # Will remove all the mocking
let me walk you through the group chat real quick π:
- β¨
use Test2::Mock;anduse MyClass;β you gotta bring both of them to the party. - β¨
track => $BOOL, # enable call tracking if desiredβ the comment says it all: call tracking is optional, so flip that$BOOLif you want it, leave it if you don't π. - β¨
class => 'MyClass',β this is you telling it which package we're messing with. - β¨
override => [ name => sub { 'fred' }, ... ]β overriding a method that already exists. herenamegets replaced with a sub that just returns'fred'π. - β¨
add => [ is_mocked => sub { 1 } ... ]β adding brand-new methods that weren't there before.is_mockedreturns1, which, mood, honestly. - β¨ the sneaky little
...lines are just "and more of the same, you get the idea" β they're literally in the code, don't @ me π. - β¨
$mock->restore('name');β with the comment# Unmock the 'name' sub, so yeah: handnameback to its original owner π. - β¨ more
...because we're still going. - β¨
$mock = undef; # Will remove all the mockingβ and there it is. set the thing toundefand every single bit of mocking is gone. boom. clean slate π.
π§ CONSTRUCTION π§
okay this is the section where we get into how you actually build one of these bad boys β and it is not over yet, so stay perched, there's more coming in the next part π«Άπ
π METHODS π
okay bestie, this is where the actual spellbook is. Every method, every argument, every βplease donβt do that unless you know what youβre doingβ β all of it, right here. πͺ
π«Ά $mock = Test2::Mock->new(class => $CLASS, ...)
This creates a brand-new Test2::Mock instance that manages mocking for the class you put in $CLASS. π
Any Test2::Mock method can be used as a constructor argument, and each one should be followed by an arrayref of arguments to use inside that method. For instance, the add() method:
my $mock = Test2::Mock->new(
class => 'AClass',
add => [foo => sub { 'foo' }],
);
is literally identical to this:
my $mock = Test2::Mock->new(
class => 'AClass',
);
$mock->add(foo => sub { 'foo' });
π $mock->track($bool)
Turns tracking on or off. Any sub that gets added, overridden, or set while tracking is on will log every call in a hash you can retrieve via $mock->tracking. Changing the tracking toggle will not affect subs that were already altered, but it will affect any additional alterations. π«Ά
π¦ $hashref = $mock->sub_tracking
The tracking data is giving this:
{
sub_name => [
{sub_name => $sub_name, sub_ref => $mock_subref, args => [... copy of @_ from the call ... ]},
...,
...,
],
}
Unlike call_tracking, this lists all calls by sub, so you can choose to only look at the sub-specific calls. π
Please note: the hashref items with the subname and args are shared with call_tracking. Modifying one modifies the other, so copy first! π
π $arrayref = $mock->call_tracking
The tracking data is giving this:
[
{sub_name => $sub_name, sub_ref => $mock_subref, args => [... copy of @_ from the call ... ]},
...,
...,
]
Unlike sub_tracking, this lists all calls to any mocked sub, in the order they were called. To filter by sub, use sub_tracking. β¨
Please note: the hashref items with the subname and args are shared with sub_tracking. Modifying one modifies the other, so copy first! π
π§Ή $mock->clear_sub_tracking() / $mock->clear_sub_tracking(\@subnames)
$mock->clear_sub_tracking()β clears ALL tracking data.$mock->clear_sub_tracking(\@subnames)β only clears those specific keys.
π§Ό $mock->clear_call_tracking()
Clears all items from call_tracking. Boom, fresh slate. β¨
π οΈ $mock->add(...) / $mock->override(...) / $mock->set(...)
$mock->add('symbol' => ..., 'symbol2' => ...)$mock->override('symbol1' => ..., 'symbol2' => ...)$mock->set('symbol1' => ..., 'symbol2' => ...)
add() and override() are the primary ways to add or modify methods for a class. Both accept the exact same type of arguments. The difference is that override will fail unless the symbol you are overriding already exists, while add will fail if the symbol does already exist. π«
set() was added more recently for cases where you may not know if the sub already exists. These cases are rare, and set should be avoided β think of it like 'no strict'. However, there are valid use cases, so it was added. π
Note: think ofoverrideas a push operation. If you call override on the same symbol multiple times, it will track that. You can userestore()as a pop operation to go back to the previous mock.resetcan be used to remove all the mocking for a symbol.
Arguments must be a symbol name, with an optional sigil, followed by a new specification of the symbol. If no sigil is specified, then '&' (sub) is assumed. A simple example of overriding a sub:
$mock->override(foo => sub { 'overridden foo' });
my $val = $class->foo; # Runs our override
# $val is now set to 'overridden foo'
You can also simply provide a value, and it will be wrapped in a sub for you:
$mock->override( foo => 'foo' );
The example above will generate a sub that always returns the string 'foo'.
There are three special values that can be used to generate accessors:
$mock->add(
name => 'rw', # Generates a read/write accessor
age => 'ro', # Generates a read only accessor
size => 'wo', # Generates a write only accessor
);
If you want a sub that actually returns one of the three special strings, or that returns a coderef, you can use a hashref as the spec:
my $ref = sub { 'my sub' };
$mock->add(
rw_string => { val => 'rw' },
ro_string => { val => 'ro' },
wo_string => { val => 'wo' },
coderef => { val => $ref }, # the coderef method returns $ref each time
);
You can also override/add other symbol types, such as a hash:
package Foo;
...
$mock->add('%foo' => {a => 1});
print $Foo::foo{a}; # prints '1'
You can also tell mock to deduce the symbol type for the add/override from the reference. The rules are similar to glob assignments:
$mock->add(
-foo => sub { 'foo' }, # Adds the &foo sub to the package
-foo => { foo => 1 }, # Adds the %foo hash to the package
-foo => [ 'f', 'o', 'o' ], # Adds the @foo array to the package
-foo => \"foo", # Adds the $foo scalar to the package
);
β©οΈ $mock->restore($SYMBOL)
Restores the symbol to what it was before the last override. If the symbol was recently added, this will remove it. If the symbol has been overridden multiple times, this will ONLY restore it to the previous state. Think of override as a push operation, and restore as the pop operation. π
π₯ $mock->reset($SYMBOL)
Removes all mocking of the symbol and restores the original symbol. If the symbol was initially added, then it will be completely removed. π«Ά
π°οΈ $mock->orig($SYMBOL)
Returns the original symbol, before any mocking. For symbols that were added, this will return undef. β¨
π $mock->current($SYMBOL)
Returns the current symbol. Periodt. π
𧨠$mock->reset_all
Removes all added symbols, and restores all overridden symbols to their originals. Full reset energy. π₯
ποΈ $mock->add_constructor($NAME => $TYPE) / $mock->override_constructor($NAME => $TYPE)
$mock->add_constructor($NAME => $TYPE)$mock->override_constructor($NAME => $TYPE)
This can be used to inject constructors. The first argument should be the name of the constructor. The second argument specifies the constructor type. π«Ά
The "hash" type is the most common β all arguments are used to create a new hash that is blessed.
hash => sub {
my ($class, %params) = @_;
return bless \%params, $class;
};
The "array" type is similar to the hash type, but accepts a list instead of key/value pairs:
array => sub {
my ($class, @params) = @_;
return bless \@params, $class;
};
The "ref" type takes a reference and blesses it. This will modify your original input argument.
ref => sub {
my ($class, $params) = @_;
return bless $params, $class;
};
The "ref_copy" type will copy your reference and bless the copy:
ref_copy => sub {
my ($class, $params) = @_;
my $type = reftype($params);
return bless {%$params}, $class
if $type eq 'HASH';
return bless [@$params], $class
if $type eq 'ARRAY';
croak "Not sure how to construct a '$class' from '$params'";
};
βͺ $mock->before($NAME, sub { ... })
This replaces the original sub $NAME with a new sub that calls your custom code just before calling the original method. The return from your custom sub is ignored. Your sub and the original both get the unmodified arguments. π
β© $mock->after($NAME, sub { ... })
This is similar to before, except your callback runs after the original code. The return from your callback is ignored. β¨
π $mock->around($NAME, sub { ... })
This gives you the chance to wrap the original sub:
$mock->around(foo => sub {
my $orig = shift;
my $self = shift;
my (@args) = @_;
...
$self->$orig(@args);
...
return ...;
});
The original sub is passed in as the first argument, even before $self. You are responsible for making sure your wrapper sub returns the correct thing. π
π€ $mock->autoload
This injects an AUTOLOAD sub into the class. This autoload will automatically generate read-write accessors for any sub called that does not already exist. Slay. π
π« $mock->block_load
This prevents the real class from loading until the mock is destroyed. This will fail if the class is already loaded. This lets you mock a class completely without loading the original module. π¦
π $pm_file = $mock->file
Returns the relative path to the file for the module. This corresponds to the %INC entry. β¨
π $bool = $mock->purge_on_destroy($bool)
When true, this causes the package stash to be completely obliterated when the mock object falls out of scope or is otherwise destroyed. You do not normally want this. π
ποΈ $stash = $mock->stash
Returns the stash for the class being mocked. This is the equivalent of:
my $stash = \%{"${class}\::"};
This saves you from needing to turn off strict. π«Ά
π·οΈ $class = $mock->class
The class being mocked by this instance. Simple, iconic. π
π― $p = $mock->parent
If you mock a class twice, the first instance is the parent and the second is the child. This prevents the parent from being destroyed before the child, which would lead to a very unpleasant situation. π³
π£ $c = $mock->child
Returns the child mock, if any. πΈ
π¦ SOURCE π¦
The source code repository for Test2-Suite can be found at https://github.com/Test-More/test-more/. π«Ά
π MAINTAINERS π
Chad Granum β exodist@cpan.org
β¨ AUTHORS β¨
Chad Granum β exodist@cpan.org
π COPYRIGHT π
Copyright Chad Granum β exodist@cpan.org.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
See https://dev.perl.org/licenses/.
okay thatβs the whole vibe check, bestie π This was Test2::Mock(3), perl v5.42.0, dated 2025-07-28 β go mock something iconic. β¨ππ¦
π¦ where this page comes from
- opensuse-leap 16.0: perl-Test-Simple 1.302214-bp160.1.2 Β· Artistic-1.0 OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms