App-SimpleBackuper
view release on metacpan or search on metacpan
local/lib/perl5/Test/Spec/Mocks.pm view on Meta::CPAN
elsif (!$original_method) {
# method didn't exist before, mimic Perl's behavior
Carp::croak sprintf("Can't locate object method \"%s\" " .
"via package \"%s\"", $self->_method, $class);
}
else {
# run the original as if we were never here.
# to that end, use goto to prevent the extra stack frame
goto $original_method;
}
});
}
sub _replace_class_method {
no strict 'refs';
my $self = shift;
my $dest = join("::", $self->_target, $self->_method);
$self->_target_class($self->_target);
$self->_original_code(defined(&$dest) ? \&$dest : undef);
$self->_install($dest => sub {
# do extreme late binding here, so calls to returns() after the
# mock has already been installed will take effect.
my @args = @_;
shift @args;
$self->_called(@args);
die $self->_exception if $self->_exception;
$self->_retval->(@_);
});
}
sub _install {
my ($self,$dest,$code) = @_;
if ($self->_original_code) {
# avoid "Prototype mismatch"
# this code borrowed/enhanced from Moose::Exporter
if (defined(my $proto = prototype $self->_original_code)) {
# XXX - Perl's prototype sucks. Use & to make set_prototype
# ignore the fact that we're passing "private variables"
&Scalar::Util::set_prototype($code, $proto);
}
}
no strict 'refs';
no warnings 'redefine';
*$dest = $code;
}
}
{
package Test::Spec::Mocks::Stub;
use base qw(Test::Spec::Mocks::Expectation);
# A stub is a special case of expectation that doesn't actually
# expect anything.
sub new {
my $class = shift;
my $self = $class->SUPER::new(@_);
$self->at_least(0);
return $self;
}
}
1;
=head1 NAME
Test::Spec::Mocks - Object Simulation Plugin for Test::Spec
=head1 SYNOPSIS
use Test::Spec;
use base qw(Test::Spec);
use My::RSS::Tool; # this is what we're testing
use LWP::UserAgent;
describe "RSS tool" => sub {
it "should fetch and parse an RSS feed" => sub {
my $xml = load_rss_fixture();
LWP::Simple->expects('get')->returns($xml);
# calls LWP::Simple::get, but returns our $xml instead
my @stories = My::RSS::Tool->run;
is_deeply(\@stories, load_stories_fixture());
};
};
=head1 DESCRIPTION
Test::Spec::Mocks is a plugin for Test::Spec that provides mocking and
stubbing of objects, individual methods and plain subroutines on both
object instances and classes. This module is inspired by and heavily
borrows from Mocha, a library for the Ruby programming language. Mocha
itself is inspired by JMock.
Mock objects provide a way to simulate the behavior of real objects, while
providing consistent, repeatable results. This is very useful when you need
to test a function whose results are dependent upon an external factor that
is normally uncontrollable (like the time of day). Mocks also allow you to
test your code in isolation, a tenet of unit testing.
There are many other reasons why mock objects might come in handy. See the
L<Mock objects|http://en.wikipedia.org/wiki/Mock_object> article at Wikipedia
for lots more examples and more in-depth coverage of the philosophy behind
object mocking.
=head2 Ecosystem
Test::Spec::Mocks is currently only usable from within tests built with
the Test::Spec BDD framework.
=head2 Terminology
Familiarize yourself with these terms:
( run in 0.944 second using v1.01-cache-2.11-cpan-97f6503c9c8 )