use warnings;
no warnings 'redefine';
use strict;
use lib '.';
use Count;
print One::foo();
{
my $count = Count->new;
my $bar = $count->mock;
print One::foo();
}
print One::foo();
####
package One;
sub foo {
return "foo\n";
}
1;
package Count;
sub new {
return bless {}, shift;
}
sub unmock {
my $self = shift;
*One::foo = \&{ $self->{sub} };
}
sub mock {
my $thing = shift;
my $self;
if (ref($thing) eq __PACKAGE__){
$self = $thing;
}
else {
$self = bless {}, __PACKAGE__;
}
$self->{sub} = \&One::foo;
*One::foo = sub { $self->{x} = 'x'; return "baz\n"; };
return $self;
}
sub DESTROY {
my $self = shift;
print "destroying...\n";
$self->unmock;
}
1;
####
my $count;
*$sub = sub {
@{ $self->{called_with} } = @_;
$self->{called_count} = ++$called;
if ($self->{side_effect}) {
if (wantarray){
my @effect = $self->{side_effect}->(@_);
return @effect if @effect;
}
else {
my $effect = $self->{side_effect}->(@_);
return $effect if defined $effect;
}
}
return undef if ! $self->{return};
return ! wantarray && @{ $self->{return} } == 1
? $self->{return}[0]
: @{ $self->{return} };
};