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 )