[rspec-users] How to mock an object defined in the before_filter function?

Evgeny Bogdanov evgeny.bogdanov at gmail.com
Thu Feb 26 03:34:05 EST 2009


Thanks a lot Pat for clear and detailed explanations.
My initial vision was that I don't change code and do all the
manipulations in spec files.
Now I understand that it is not really what I should be doing. I
should take into account both,
and adapt one to another to improve clarity and briefness of both
ones.
This might bring me to a better programming style :)

On Feb 26, 2:03 am, Pat Maddox <pat.mad... at gmail.com> wrote:
> On Wed, Feb 25, 2009 at 2:40 PM,EvgenyBogdanov
>
> <evgeny.bogda... at gmail.com> wrote:
> > The function to specify and specification for it are below.
>
> > Comment.stub!(:find).and_return(@comment)
> > does what I need.
> > However, it strongly depends on the implementation of find_comment
> > function,
> > and if I change it to, let's say, this one:
> >    def find_comment
> >       @space = Space.find(1)
> >       @comment = @space.comment
> >     end
>
> My personal opinion is that the semantics of your app have changed, so
> at least some spec somewhere should have to change with it.  There are
> a lot of people who don't agree with that.
>
> > my spec will fail. Moreover, in my spec I'm checking if the
> > destroy.rjs is returned on request,
> > and I don't care about @comment and find_comment. Thus, I would like
> > just to mock the whole
> > object @comment for the function "destroy" like it is done with
> > assigns for view specs, so that my spec doesn't depend on it at all.
>
> I would wrap the stubbing stuff in a method, so that you clearly show
> in your test that you don't care about the comment.  e.g.
>
> # spec_helper.rb
> def stub_comment
>   c = mock_model(Comment)
>   Comment.stub!(:find).and_return c
>   c
> end
>
> describe CommentsController, "DELETE /comments/1" do
>   before(:each) do
>     stub_comment
>   end
>
>   ...
> end
>
> Another alternative is to not use a @comment ivar in your controllers
> and instead to use a method.  e.g.
>
> def comment
>   @comment ||= Comment.find params[:id]
> end
>
> and wherever you reference @comment in the controller, ref the method
> comment instead.  Then in your spec you can stub it.
>
> You need to inject your mock somehow, but due to the design of Rails
> controllers you can't really just "set" something in there, so you
> need to either use a factory method which you stub in the controller
> spec, or stub out the finder.  If you think that the setup is too
> verbose, wrap it in an intention-revealing method.
>
> Pat
>
> Pat
> _______________________________________________
> rspec-users mailing list
> rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users


More information about the rspec-users mailing list