Test::Resub(3)
π Test::Resub β like, the manual page, bestie
okay so picture this: you're in Test::Resub (3), a Perl module, and honestly it's giving main character energy for test suites. Lexically scoped monkey patching?? for testing?? yes queen. Let's get into it π«Ά
β¨ NAME β¨
Test::Resub β lexically scoped monkey patching for testing. no cap, that's literally the whole vibe π
β¨ SYNOPSIS β¨
#!/usr/bin/perl
use Test::More tests => 4;
use Test::Resub qw(resub);
{
package Somewhere;
sub show {
my ($class, $message) = @_;
return "$class, $message";
}
}
# sanity
is( Somewhere->show('beyond the sea'), 'Somewhere, beyond the sea' );
# scoped replacement of subroutine with argument capturing
{
my $rs = resub 'Somewhere::show', sub { 'hi' };
is( Somewhere->show('over the rainbow'), 'hi' );
is_deeply( $rs->method_args, [['over the rainbow']] );
}
# scope ends, resub goes away, original code returns
is( Somewhere->show('waiting for me'), 'Somewhere, waiting for me' );
see how the original code just... comes back when the scope ends? that's the whole slay π
β¨ DESCRIPTION β¨
so this module lets you temporarily replace a subroutine/method with arbitrary code. iconic. and then later you can find out how many times it was called, and with what arguments each time. it's giving surveillance but make it cute π
ngl, you may not actually need this module. a lot of the time you can get away with something like this:
{
no warnings 'redefine'
local *Somewhere::show = sub { return 'kwaa' };
is( Somewhere->show('me the money'), 'kwaa' );
}
but this module is genuinely handy if you're replacing a subroutine with a function prototype, or for when you need to prove the inputs to the functions that you're calling. that's the highkey useful part, iykyk π₯
β¨ CONSTRUCTOR β¨
use Test::Resub qw(resub);
my $rs = resub 'package::method', sub { ... }, %args;
is equivalent to:
use Test::Resub;
my $rs = Test::Resub->new(
name => 'package::method',
code => sub { ... },
%args,
);
%args can be any of the following named arguments:
nameβ the function/method which is to be replaced.codeβ the code reference which will replacename. Defaults tosub {}captureβ boolean which indicates whether or not arguments should be captured. A warning is emitted if you try to look at args without specifying atruecapture. Defaults to 0.callβ one of the following values (defaults to'required'):requiredβ if the subroutine/method was never called when the Test::Resub object is destroyed,not ok 1000is printed to STDOUT.forbiddenβ if the subroutine/method was called when the Test::Resub object is destroyed,not ok 1000is printed to STDOUT.optionalβ it doesn't matter if the subroutine/method gets called. π«Ά As a general rule, your tests should know whether or not a subroutine/method is going to get called, so avoid using this option if you can. (bestie she's telling you something fr fr)
createβ boolean which indicates whether or not a function will be created if none exists. If the package can't resolve the method (i.e. !UNIVERSAL::can($package, $method)), then an exception will be thrown unless'create'is true. Defaults to false. This is mainly useful to catch typos. β¨deep_copyβ whether or not to make a deep copy of saved-off arguments. Default is 0. Occassionally one wants deep copies, but there is an associated performance penalty, e.g. for large objects. Things like filehandles and sockets don't perform well with deep_copy, and can cause superfluous test failures. Enable this with caution.
β οΈ about that deep_copy one β filehandles and sockets + deep_copy = sad tests. seriously, caution. she's not being dramatic for no reason π
β¨ METHODS β¨
calledβ returns the number of times the replaced subroutine/method was called. Theresetmethod clears this data.not_calledβ returns true if the replaced subroutine/method was never called. Theresetmethod clears this data.was_calledβ returns the total number of times the replaced subroutine/method was called. This data is not cleared by theresetmethod. πresetβ clears thecalled,not_called, andargsdata.argsβ returns data on how the replaced subroutine/method was invoked. Examples:
Invocations: C<args> returns:
---------------------------- -------------------------
(none) []
foo('a'); [['a']]
foo('a', 'b'); foo('d'); [['a', 'b'], ['d']]
named_argsβ likeargs, but each invocation's arguments are returned in a hashref. Examples:
Invocations: C<named_args> returns:
---------------------------- -------------------------
(none) []
foo(a => 'b'); [{a => 'b'}]
foo(a => 'b', c => 'd'); foo(e => 'f');
[{
a => 'b', c => 'd',
}, {
e => 'f',
}]
the arg_start_index argument specifes that a certain number of arguments are to be discarded. For example:
my $rs = resub 'some_sub';
...
some_sub('one', 'two', a => 1, b => 2);
...
$rs->named_args(arg_start_index => 1);
# returns ['two', {a => 1, b => 2}]
$rs->named_args(arg_start_index => 2);
# returns [{a => 1, b => 2}]
the scalars argument specifies that a certain number of scalar arguments precede the key/value arguments. For example:
my $rs = resub 'some_sub';
...
some_sub(3306, a => 'b', c => 123);
some_sub(9158, a => 'z', c => 456);
...
$rs->named_args(scalars => 1);
# returns [3306, {a => 'b', c => 123},
# 9158, {a => 'z', c => 456}]
note that named_args(scalars => N) will yield N scalars plus one hashref per call regardless of how many arguments were passed to the subroutine/method. For example:
my $rs = Test::Resub->new({name => 'some_sub'});
...
some_sub('one argument only');
some_sub('many', 'arguments', a => 1, b => 2);
...
$rs->named_args(scalars => 2);
# returns ['one argument only', undef, {},
# 'many', 'arguments', {a => 1, b => 2}]
method_argsβ likeargs, but the first argument of each invocation is thrown away. ποΈ This is used when you're resub'ing an object or class method and you're not interested in testing the object or class argument. Examples:
Invocations: C<method_args> returns:
---------------------------- -------------------------
(none) []
$obj->foo('a'); [['a']]
Class->foo('a', 'b'); Class->foo('d'); [['a', 'b'], ['d']]
named_method_argsβ likenamed_args, but the first argument of each invocation is thrown away. This is used when you're resub'ing an object or class method and the arguments are name/value pairs. Examples:
Invocations: C<named_args> returns:
---------------------------- -------------------------
(none) []
$obj->foo(a => 'b'); [{a => 'b'}]
$obj->foo(a => 'b', c => 'd'); [{
Class->foo(e => 'f'); a => 'b', c => 'd',
}, {
e => 'f',
}]
named_method_args also takes a scalars named argument which specifies a number of scalar arguments preceding the name/value pairs of each invocation. It works just like named_args except that the first argument of each invocation is automatically discarded. For example:
my $rs = resub 'SomeClass::some_sub';
...
SomeClass->some_sub(3306, a => 'b', c => 123);
SomeClass->some_sub(9158, a => 'z', c => 456);
...
$rs->named_method_args(scalars => 1);
# returns [3306, {a => 'b', c => 123},
# 9158, {a => 'z', c => 456}]
note: the first argument is automatically discarded before the optional arg_start_index parameter is applied. That is,
my $rs = resub 'SomeClass::some_sub';
...
SomeClass->some_sub('first', b => 2);
...
$rs->named_method_args(arg_start_index => 1);
# returns [{b => 2}]
β¨ HISTORY β¨
written at AirWave Wireless for internal testing, 2001-2007. Tidied up and released to CPAN in 2007. AirWave was subsequently acquired by Aruba Networks in 2008. Aruba Networks transferred ownership, future development, and copyright of future development to Belden Lyman in early 2012. See the Changes file for changes. π
β¨ AUTHOR β¨
The development team at AirWave Wireless, http://www.airwave.com/
π please do not submit bug reports to the Airwave Wireless team. Send them to the maintainer (below) or submit them at https://github.com/belden/test-resub/issues β she said what she said π
β¨ MAINTAINER β¨
Belden Lyman <belden@cpan.org>
The latest copy of this package can be checked out from GitHub at http://github.com/belden/test-resub π¦
β¨ COPYRIGHT AND LICENSE β¨
(c) 2001-2008 AirWave Wireless, Inc.
(c) 2008-2012 Aruba Wireless Networks, Inc.
(c) 2012- Belden Lyman
This module is free software; you can redistribute it or modify it under the terms of Perl itself. π
and that's the whole page bestie β sign-off time: this was perl v5.42.2, dated 2026-02-15, page Test::Resub(3). go forth and monkey patch responsibly πβ¨πΈ
π¦ where this page comes from
- alpine 3.24: perl-test-resub-doc 2.03-r6 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms