[Rspec-devel] New proc.should_increment method

aslak hellesoy aslak.hellesoy at gmail.com
Fri Jul 14 17:22:42 EDT 2006


On 7/14/06, David Chelimsky <dchelimsky at gmail.com> wrote:
> On 7/14/06, aslak hellesoy <aslak.hellesoy at gmail.com> wrote:
> > That sounds good. I'm looking forward to that.
> >
> > One thing I'd like to instead of:
> >
> >   thing = mock("thing")
> >
> > is to do:
> >
> >   thing = mock(Thing) # passing a class rather than a string
> >
> The way it works now does something similar, but is implemented
> differently. You tell a class to act like a mock:
>
> class Thing; acts_as_mock; end
>
> Then you can do this:
>
> thing = Thing.new
> thing.should_receive(:some_message)
> Thing.should_receive(:new).and_return(thing)
>
> post :create
>
> Thing.__verify
> thing.__verify
>
> etc
>
> (Once fully  integrated w/ rspec the verification should be automagic.)
>
> Now you've got a handle on the object that is acting like a mock. If
> you want you can do this:
>
> thing = Mock.new("thing")
> thing.should_receive(:some_message)
> Thing.should_receive(:new).and_return(thing)
>
> instead. Then you'd get an instance of Mock rather than an instance of
>  Thing that's acting like one.
>
> Also, the way acts_as_mock handles messages is a bit different from
> rspecs current mocks. Rather than using message_missing and comparing
> the message to expectations, it actually adds methods to the mock when
> you set expectations. So when you do this:
>
> mock.should_receive(:message).and_return(:object)
>
> this is what happens internally:
>
>         def should_receive message
>           (class << self; self; end).class_eval do
>             define_method(message.to_s, lambda {received_message message})
>           end
>           @messages_expected << message
>           self
>         end
>
> received_message (which gets called by the newly created method) then
> checks against @messages_expected. There's more to it than that, but
> that's the basic idea.
>

I like that, and I think we should refactor the vanilla mocks to use
this approach too. There is no need to use method_missing really.

Aslak

> More soon........
>
> > -and have the mock fail if you tell it to expect a message that is not defined by Thing.
>
> Interesting, but that goes against something I'm shooting for in rails
> controller tests. I want to decouple them completely from the db.
> Since AR defines methods on the fly based on DB structure, those
> methods wouldn't be there and the mock would fail.
>
> There is something interesting here though - maybe we could have an
> argument to acts_as_mock that tells it to behave this way when we want
> to (raising flags when methods aren't part of the class), but
> otherwise not.
>
> When testing controllers, we could set that flag and force the
> controller to only call methods that we actually write in to the model
> classes, and therefore not use any of the read accessors that are
> created for attributes by AR.
>
> Then, when testing views, we would turn the flag off and tell the mock
> to return an empty string for any getters it calls that we haven't
> specified how the mock should behave.
>
> Too complex? Maybe. This is all stuff we can add later if we agree it
> makes sense. First things first.
>
> Thoughts?
> _______________________________________________
> Rspec-devel mailing list
> Rspec-devel at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-devel
>


More information about the Rspec-devel mailing list