Writing controller specs

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

Howdy. I’ve been handling this by simply stubbing out the methods as
needed in the before(:each) block and then stating
should_receive(:foo) when i’m actually writing spec for their
behavior.

RSL

Take a look at before(:each) -
http://rspec.rubyforge.org/documentation/index.html

Pat