[mocha-developer] Organizing tests and mocha expectations
James Mead
jamesmead44 at gmail.com
Mon Oct 9 04:45:37 EDT 2006
On 09/10/06, Bryan Helmkamp <bhelmkamp at gmail.com> wrote:
>
> I'm simultaneously getting into using Mocha and RSpec-style tests
> (courtesy of the simply_bdd plugin) and I'm struggling with some
> issues while trying to organize my specs/test. Here's a code example
> illustrating the problem:
>
> context "update cliient invalid data" do
> include ClientsControllerSpecHelper
>
> specify "should render edit form" do
> setup_controller
>
> @client = mock
> Client.expects(:find).with("1").returns(@client)
>
> @client.expects(:attributes=).with("attributes")
> @client.expects(:save!).raises(ActiveRecord::RecordInvalid.new
> (stub(:errors
> => stub(:full_messages => []))))
>
> @controller.expects(:render).with()
> @controller.expects(:render).with(:action => "edit")\
>
> put :update, :id => 1, :client => "attributes"
> end
> end
>
> Now, to fit well with RSpec's methodology, I'd like to have a setup
> method which gets the context ready, and then follow that up with some
> specifications. Essentially here's the logic:
>
> Update client with invalid data
> - Should find client by id
> - Should attempt to save client with new attributes
> - Should render edit form
>
> The problem is that I can't break the expectations up into separate
> test methods like that because all the tests depend on those in order
> to work. It's as if each of those expectations is both setup code and
> a test, and each test relies on all the setup code for the whole test
> case.
>
> Is there anyway to reorganize this code to still be DRY but yet also
> achieve more granular tests, despite their interdependencies?
>
> Thanks,
>
> -Bryan
If I understand correctly, I think your problem boils down to the fact that
the mock is providing two pieces of functionality for each expectation - (1)
asserts that a particular method has been called with particular parameters;
(2) returns a specified result (stubbing). I'm not overly familiar with the
BDD style, but the only way I can see you could do this at the moment is...
context "update cliient invalid data" do
include ClientsControllerSpecHelper
specify "should find client by id" do
setup_controller
@client = mock
Client.expects(:find).with("1").returns(@client)
@client.stubs(:attributes=)
@client.stubs(:save!).raises(ActiveRecord::RecordInvalid.new(stub(:errors
=> stub(:full_messages => []))))
@controller.stubs(:render)
put :update, :id => 1, :client => "attributes"
end
specify "should attempt to save client with new attributes" do
setup_controller
@client = mock
Client.stubs(:find).returns(@client)
@client.expects(:attributes=).with("attributes")
@client.expects(:save!).raises(ActiveRecord::RecordInvalid.new(stub(:errors
=> stub(:full_messages => []))))
@controller.stubs(:render)
put :update, :id => 1, :client => "attributes"
end
specify "should render edit form" do
setup_controller
@client = mock
Client.stubs(:find).returns(@client)
@client.stubs(:attributes=)
@client.stubs(:save!).raises(ActiveRecord::RecordInvalid.new(stub(:errors
=> stub(:full_messages => []))))
@controller.expects(:render).with()
@controller.expects(:render).with(:action => "edit")
put :update, :id => 1, :client => "attributes"
end
end
...admittedly not very DRY, but I don't think DRY-ness is as important as
readability in tests.
However this reminds me of a conversation I had a while ago with my
colleague Chris Roos. We were discussing the possibility of replacing one
expectation with another. If we could do this then it might be possible to
do something like this...
context "update cliient invalid data" do
include ClientsControllerSpecHelper
setup do
setup_controller
@client = mock
Client.stubs(:find).returns(@client)
@client.stubs(:attributes=)
@client.stubs(:save!).raises(ActiveRecord::RecordInvalid.new(stub(:errors
=> stub(:full_messages => []))))
@controller.stubs(:render)
end
specify "should find client by id" do
Client.expects(:find).with("1").returns(@client)
put :update, :id => 1, :client => "attributes"
end
specify "should attempt to save client with new attributes" do
@client.expects(:attributes=).with("attributes")
@client.expects(:save!).raises(ActiveRecord::RecordInvalid.new(stub(:errors
=> stub(:full_messages => []))))
put :update, :id => 1, :client => "attributes"
end
specify "should render edit form" do
@controller.expects(:render).with()
@controller.expects(:render).with(:action => "edit")
put :update, :id => 1, :client => "attributes"
end
end
...I'm guessing this is more like what you're after. If yes, let me know and
we'll look into making the change.
--
James.
http://blog.floehopper.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://rubyforge.org/pipermail/mocha-developer/attachments/20061009/655df30c/attachment.html
More information about the mocha-developer
mailing list