[mocha-developer] Proxies

Duncan Beevers duncanbeevers at gmail.com
Wed Jan 2 15:55:31 EST 2008


I really like the idea of Mock Proxies as explained in Brian Takita's post here:
http://pivots.pivotallabs.com/users/brian/blog/articles/352-introducing-rr

I posted to this list eariler with an incomplete implementation of
.stops_mocking in the thread "Mocking Time, delegating to original
object."  The Mock Proxy pattern would make this simpler.

Proxy(User).expects(:find).with(99) # Sets expectation, forwards
method invocation to original class
User.expects(:find).with(99).returns(nil).then.proxies # Canned
response, then forwards successive invocations to original class.

Most of this is just my desire to be lazy and not actually have to
unit-test *trivial* methods explicitly.  I also like the idea of using
the Mock Proxy to exercise the behavior of simple private instance
methods of my class which are kind of a pain to test currently, which
leads to my not making anything private.

On Jan 2, 2008 6:50 AM, James Mead <jamesmead44 at gmail.com> wrote:
>
> On 05/11/2007, Duncan Beevers <duncanbeevers at gmail.com> wrote:
> > The block syntax looks excellent, and reads very nicely.  I especially
> > like the idea of not having to pass in the mock to the block to stick
> > the expectations onto, and instead just continue fluently adding
> > expectations.
> >
> > This block syntax also feels like the right direction to go if there
> > were to be some kind of expectations on the ordering of method calls.
> > I haven't run into a testing situation where I've needed to test the
> > ordering of calls on a mock explicitly, but flex mock provides a
> > grouping mechanism.
> >
> > For the corollary in FlexMock, check out #ordered
> > http://onestepback.org/software/flexmock/classes/FlexMock/Expectation.html#M000082
> >
> > Don't take me too seriously, but I think mocha could trump flexmock's
> > with something like:
> >
> > mock_user = mock('User') do
> >   initially.expects(:first_name).returns('Duncan')
> >   then.expects(:last_name).returns('Beevers')
> >
> >   later.expects(:birthday).returns('a gentleman never asks')
> >   then.expects(:astrological_sign).returns('Virgo')
> >
> >   stubs(:favorite_color).returns('silver')
> >
> >   finally.expects(:goodnight!).returns('same to you')
> > end
> >
> > Where the temporal prefixes initially, finally, then and later
> > indicate method call ordering, and expectations without a temporal
> > prefix can be called freely.
> >
> > Am I pulling this out of my ass?  Yes.
> >
> > On Nov 4, 2007 3:19 PM, James Mead <jamesmead44 at gmail.com> wrote:
> > >
> > > On 04/11/2007, Duncan Beevers <duncanbeevers at gmail.com> wrote:
> > > >
> > > > I was reading through the FlexMock docs and noticed the expectation
> > > > method .mock, which returns the original mock associated with an
> > > > expectation.
> > > >
> > > > It looks really handy for writing nice all-in-one mocks like:
> > > >
> > > > mock_user = mock('User').expects(:first_name).returns('Jonah').mock
> > > >
> > > > So I started playing around with mocha and found I could actually
> > > > already do this!
> > > > But I'm not sure how.  There's no attr_reader on @mock, and I couldn't
> > > > find out where this method is defined.
> > > >
> > > > So, perhaps we could add this an explicit method on Expectation and
> > > > include a little rdoc on it?
> > > > I think a lot of people would get benefit from making this explicit.
> > > >
> > > > Opinions?
> > > >
> > >
> > > Hmm. I think this may have disappeared in some recent refactoring in trunk.
> > > Rather than exposing too much of the internals, I keep meaning to add a
> > > syntax like this...
> > >
> > >   mock_user = mock('User') {
> > >     expects(:first_name).returns('James')
> > >     stubs(:last_name).returns('Mead')
> > >   }
> > >
> > > Would that help you do what you want to do...?
> > >
> > > Alternatively did you know you could already do...
> > >
> > >   mock_user = mock('User', :first_name => 'James', :last_name => 'Mead')
> > >
> > > However there are a couple of limitations with this - you can't mix expects
> > > & stubs and you can't specify anything other than a returns() e.g. no
> > > with(), no raises(), etc.
> > >
> > >
> > > What do you think?
> > > --
> > > James.
> > > http://blog.floehopper.org
> > > http://tumble.floehopper.org
> > > _______________________________________________
> > > mocha-developer mailing list
> > > mocha-developer at rubyforge.org
> > > http://rubyforge.org/mailman/listinfo/mocha-developer
> > >
> > _______________________________________________
> > mocha-developer mailing list
> > mocha-developer at rubyforge.org
> > http://rubyforge.org/mailman/listinfo/mocha-developer
> >
>
> Sorry for taking ages to respond to this. I just wanted to let you
> know that since revision 193 (which is included in gem 0.5.6), the
> initializer block syntax has been available. Unfortunately the rdoc
> didn't get updated until revision 221 (which hasn't yet been
> released).
>
> Since your email, I've added support for JMock2 style sequences [1]
> and states [2] which allow you to constrain the order of invocation. I
> haven't yet sorted out the error reporting and there may be some
> teething problems, but feel free to give it a try. All the rdoc has
> been updated in trunk. See AutoVerify#sequence and AutoVerify#states
> for details.
>
> In the meantime - thanks for you interest and your suggestions.
> --
> James.
> http://blog.floehopper.org
> http://tumble.floehopper.org
>
> [1] http://jmock.org/sequences.html
> [2] http://jmock.org/states.html
>
> _______________________________________________
> mocha-developer mailing list
> mocha-developer at rubyforge.org
> http://rubyforge.org/mailman/listinfo/mocha-developer
>


More information about the mocha-developer mailing list