Frustrations with rSpec
Posted by sam, Sun Feb 24 22:32:00 UTC 2008
I'm working on the new blog, and I'm having some trouble with rSpec testing controllers and nested routes.
Here's my routes file
ActionController::Routing::Routes.draw do |map|
map.root :controller => "frontpage"
map.resources :posts, :has_many => :comments
end
And here is some of the controller specs I'm trying to test
require File.dirname(__FILE__) + '/../spec_helper'
describe CommentsController do
describe "handling GET /posts/1/comments" do
before(:each) do
@comment = mock_model(Comment)
Comment.stub!(:find).and_return(@comment)
@post = mock_model(Post)
@post.stub!(:comments)
@post.comments.stub!(:find).and_return([@comment])
Post.stub!(:find).and_return(@post)
end
def do_get
get :index, :post_id =>@post.id
end
it "should be successful" do
do_get
response.should be_success
end
it "should render index template" do
do_get
response.should render_template('index')
end
it "should find all comments" do
Comment.should_receive(:find).with(:all).and_return([@comment])
do_get
end
it "should assign the found comments for the view" do
do_get
assigns[:comments].should == [@comment]
end
end
Here's the controller
class CommentsController < ApplicationController
# GET /comments
# GET /comments.xml
before_filter :load_post
def index
@comments = @post.comments.find(:all)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @comments }
end
end
protected
def load_post
@post = Post.find(params[:post_id])
end
end
Everything works, except for one spec:
When I try to run the spec on "it should find all comments" I get this error
Mock 'Class' expected :find with (:all) once, but received it 0 times
I don't know what to do. I'm trying to understand what I'm doing. Mocks and Stubs are a big leap of faith for someone who grew up using full blown fixtures. I hope my other specs aren't passing due to dumb luck or something like that.
Should I wait and try to do this in the Stories? Is it useful to to rSpec mocks and stubs for a nested resource?
Any ideas? Fire away in the comments.
BTW, I'm using the great article Rolling on Rails with Rails2.0 from Akita on Rails as a starting point for my new blog.
Thanks for the great article!




Hey Sam! The problem you're having there is that your expectation is that the Class 'Comment' will receive :find, but in fact what really happens it that the model @post receives :find. Change your spec to read: @post.shouldreceive(:find).with(:all).andreturn([@comment]) and I think you'll have better results. Good luck!