Ovid wrote: > ----- Original Message ---- > From: Michael G Schwern <[EMAIL PROTECTED]> > >> How does it know when the is_broken tests have finished and the twinkletoes >> tests have begun? > > First, I think the method name should be 'mock_once' and each sub gets > wrapped with Hook::LexWrap > or something similar. Writing the code to see if the mocked sub has been called is trivial. If you > need to have the mocked sub run more than once, list it more than once
It would seem to need intimate knowledge of the internals of whatever you're testing. Let's look at your example. sub _validate { my $self =shift; if ( $self->is_broken ) { throw_some_exception "we're broken" } if ( $self->username ) { throw_another_exception "we gots a bucket, er, user" } if ( $self->is_inflatable ) { throw_up "a.k.a., 'unswallowing'" } } $some_class->mock_once( is_broken => 1, username => 'twinkletoes', is_inflatable => 1 ); my $obj = $some_class->new; dies_ok { $obj->validate } "we're broken"; dies_ok { $obj->validate } "we gots a bucket, er, user"; dies_ok { $obj->validate } "a.k.a., 'unswallowing'"; Now what happens if the order of things checked in the validation routing is changed while keeping the tests the same? A good test should weather this. sub _validate { my $self =shift; if ( $self->username ) { throw_another_exception "we gots a bucket, er, user" } if ( $self->is_inflatable ) { throw_up "a.k.a., 'unswallowing'" } if ( $self->is_broken ) { throw_some_exception "we're broken" } } $some_class->mock_once( is_broken => 1, username => 'twinkletoes', is_inflatable => 1 ); my $obj = $some_class->new; # Fails, "we gots a bucket, er, user" dies_ok { $obj->validate } "we're broken"; # Fails "unswallowing" dies_ok { $obj->validate } "we gots a bucket, er, user"; # Fails "we're broken" dies_ok { $obj->validate } "a.k.a., 'unswallowing'"; Also consider what happens should _validate() call a mock_once method twice. Or since the mocking is class-wide if a method is called on another object? The setup is very brittle because it uses a single setup for three tests. What you really want is something lexical where each setup is explicitly related to the test. This is easier to read, more robust and more generally useful. { my $sentry = $some_class->tmp_mock( is_broken => 1 ); dies_ok { $obj->validate } "we're broken"; } { my $sentry = $some_class->tmp_mock( username => 'twinkletoes' ); dies_ok { $obj->validate } "we gots a bucket, er, user"; } { my $sentry = $some_class->tmp_mock( is_inflatable => 1 ): dies_ok { $obj->validate } "a.k.a., 'unswallowing'"; } PS Its a strange validation routine that dies on the presence of certain values rather than their absence. How will mock_once() work with that sort of validate()?