Question re: stubbing out validations


#1

Suppose a “User” has many “widgets”, and that we have a method in the
User
class that does something like:

def update_widgets
x = … code to do some calculations …
if x > 5
new_widget = widgets.new
new_widget.save!
else
widgets.first.destroy
end

widgets.reload
end

How would one spec this without having to worry about the validations
for
new_widget? Is there any way in the spec to tell it to replace
instances of
save! with instances of save(false) or something along those lines?
Using
message expectations is difficult in this case because the new_widget
doesn’t exist before the method is called, so there’s not object that
can
ahead of time expect to receive the save! method.

Thanks…


#2

On 11 May 2009, at 17:05, Barun S. wrote:

end
receive the save! method.
If you have a user object in your specs, you could do this:

user.widgets.stub!(:new).and_return(mock(Widget, :save! => nil))

but you’re getting into some ugly territory mixing mocks with calls to
the database (e.g. widgets.reload).

What does your spec look like?

Matt W.
http://blog.mattwynne.net
http://www.songkick.com


#3

Yes, that mixture of mocking and database calls is what was giving me a
lot
of headache. And with my actual code more than one object might be
created
in the method so stubbing out the :new method would have added a lot of
complication to my specs if I were to maintain good coverage. I tried
using

Widget.any_instance.stub!(:valid?).and_return(false)
but this didn’t work for me (doing a google search reveals that perhaps
I’d
have to apply some sort of patch to get this functionality, which I am
not
so keen on doing).

For now I’ve overcome this problem by just writing my specs in such a
way
that I ensure that new_widget is a valid object. Some of the attributes
assigned to new_widget before it is saved are dependent upon objects and
fields that I am mocking or stubbing in my specs. I was using
oversimplified mocks, thinking I should be able to avoid dealing with
validation since that is tested elsewhere already. But, not having
found a
way to do that I am now using more realistic mocks so that the
new_widget.save! method does not raise an error anymore.


#4

On Mon, May 11, 2009 at 12:05 PM, Barun S. removed_email_address@domain.invalid wrote:

end

widgets.reload
end

How would one spec this without having to worry about the validations for
new_widget?

It seems pretty important that update_widgets is able to produce
actual widgets. I would use actual models here rather than try to
stub/mock something out. After all the whole method is about creating
(or destroying) the widgets. It seems pretty central to the behaviour
of the method. However, if what you shared is the “dumbed” down
version of your code for us on the ML then perhaps there is something
complicated going on that makes it a good candidate to be designed
differently.

Is there any way in the spec to tell it to replace instances of
save! with instances of save(false) or something along those lines? Using
message expectations is difficult in this case because the new_widget
doesn’t exist before the method is called, so there’s not object that can
ahead of time expect to receive the save! method.

Are you telling us the full story? In the above code you shared you
don’t pass any attributes into “widget.new”. So, how does it create
valid widgets in the actual app?

Thanks…


rspec-users mailing list
removed_email_address@domain.invalid
http://rubyforge.org/mailman/listinfo/rspec-users


Zach D.
http://www.continuousthinking.com (personal)
http://www.mutuallyhuman.com (hire me)
@zachdennis (twitter)