NAME

Sub::Stubber - Self-monkeypatch your on demand.

SYNOPSIS

package Expensive;
use Sub::Stubber;
use base qw(Sub::Stubber Exporter);

our @EXPORT = qw(expensive_1 expensive_2);
Sub::Stubber->regstubs(@EXPORT);
Sub::Stubber->add_trigger(import => '__USE_STUBS__');
Sub::Stubber->add_trigger(env => EXPENSIVE_USE_STUBS);

sub expensive_1 ($$) {
    sleep(100);
}
sub expensive_2 (@) {
    sleep(200);
}

Meanwhile, in calling code:

use Expensive qw(__USE_STUBS__);
expensive_1 'foo', 'bar'; #returns immediately
my @l;
expensive_2 @l; #returns immediately

From the command line:

EXPENSIVE_USE_STUBS=1 perl -MExpensive -e 'expensive_1 1,2'

DESCRIPTION

Sub::Stubber allows for modules to conveniently change their containing functions into stubs. This is useful for code which by default does expensive operations, but which may not be desired for one-off cases, such as test environments or scripts - or in cases where calling code knows that those functions will never need to return anything significant.

The 'stubification' of the modules is hard. This does not attempt to merely export stubbed functions to calling code, but will override the actual functions with their stubbed versions, so exported, fully qualified and intra-package calls to these functions will all use the stubs instead.

If you would like to see a more export-oriented module, have a look at Sub::Exporter.

This module has no exports of its own, and its functionality is available via inheritance and/or package methods:

Sub::Stubber->regstubs(...)

Register one or more sub specifications to be used in conjunction with the calling package.

A stub specification can either be a simple name, or a hash reference.

String
Sub::Stubber->regstubs('foo_function');

When strings are used, a function returning undef will be triggered for it.

Hash Reference
Sub::Stubber->regstubs( { 
    get_everything => 42 
} );
Sub::Stubber->regstubs( { 
    naive_implementation => sub { rand(10) } 
} );

Hash reference specifications can contain one or more key-value pairs. The keys are the function names to be replaced. The value can either be a simple scalar, or a CODE reference.

In the case of the former, the value is returned as is from the function. In the case of the latter, the CODE reference itself is interpreted to be the replacement function. [ If you need to have a function which itself actually returns a function, you should provide a CODE reference which does just that ].

Prototypes are fetched from the original function and applied to the new one.

It is also possible to specify multiple definitions in a single call, thus, the following is perfectly valid:

Sub::Stubber->regstubs(
    'foo_function',
    {
        get_everything => 42,,
        naive_implementation => sub { rand(10) }
    }
);

Sub::Stubber->add_trigger(trigger_type, trigger_name)

Modules need to know when they need to generate a trigger function.

The trigger_type argument specifies what type of trigger should be added, and trigger_name is the name of that trigger.

Note that triggers only have meaning within Sub::Stubber's import function, but should work as a standalone in a future release.

The triggers provided are:

env

Check the environment to see if a specific flag trigger_name is set to true.

import

Check arguments passed to import for a token matching trigger_name.

Sub::Stubber->mkstubs(extra stub specifiers)

'Stubbify' the functions registered with regstubs and/or additional stub specifiers passed as arguments to mkstubs.

This does not do checking on environment variables, and should be used from your own import function, if Sub::Stubber's import isn't sufficient.

INHERITING

You can inherit from Sub::Stubber. Inheriting provides an import method which works with Exporter, and allows it to scan special import-time tokens and/or environment variables specifying whether functions should be stubbified.

If you choose to inherit from this module, ensure that Sub::Stubber's import gets called first by placing it at the beginning of your module's @ISA.

Thus:

our @ISA = qw(Sub::Stubber Exporter);

TODO

Make this module more friendly for code which doesn't like to inherit it.

AUTHOR & COPYRIGHT

Copyright (C) 2012 M. Nunberg

You may use and distribute this software under the same terms and conditions as Perl itself.