One thing that is bothering me about my controller specs is that
sometimes I end up with a number of examples that are the same except
for the example name.
The reason that this happens is that I’ve expressed all the expected
behavior with should_receive. While this does more or less work as
intended it doesn’t feel right.
As an example, let’s say I’m writing code to post a comment and record
the IP address. First, let’s handle the comment posting:
describe ‘post comment’ do
before do
@data = {‘text’ => ‘A comment that is posted’}
@comment = mock_model(Comment)
end
it ‘should be successful when proper input has been given’ do
Comment.should_receive(:new).with(@data).once.and_return(@comment)
@comment.should_receive(:save).and_return(true)
post :create, {:comment => @data}
response.should be_success
end
end
So far so good, although checking the response doesn’t feel exactly
right.
Then again, the two expectations already cover the example, so checking
the
response could just as well be left out.
Now, on to adding the recording of the IP address:
it ‘should record the IP address of the poster’ do
@comment.should_receive(:ip_address=).with(‘0.0.0.0’)
post :create, {:comment => @data}
end
Obviously this won’t work because the @comment object has not been set
up correctly. So, we should also add in that code:
it ‘should record the IP address of the poster’ do
Comment.should_receive(:new).with(@data).once.and_return(@comment)
@comment.should_receive(:save).and_return(true)
@comment.should_receive(:ip_address=).with(‘0.0.0.0’)
post :create, {:comment => @data}
end
But now the initial example won’t work anymore because the mock model
doesn’t deal with the ip_address= method. Let’s fix that as well:
it ‘should be successful when proper input has been given’ do
Comment.should_receive(:new).with(@data).once.and_return(@comment)
@comment.should_receive(:save).and_return(true)
@comment.should_receive(:ip_address=).with(‘0.0.0.0’)
post :create, {:comment => @data}
response.should be_success
end
So now both methods look the same (minus the gratuitous response
check) and it feels like something went wrong somewhere. It even
becomes tempting to move the should_receive lines into the before-do
block, but then the examples become essentially empty.
Any comments on insight into this would be appreciated.
Kind regards,
Hans