Skip to content

Instantly share code, notes, and snippets.

@ches
Created February 8, 2012 00:36
Show Gist options
  • Save ches/1763572 to your computer and use it in GitHub Desktop.
Save ches/1763572 to your computer and use it in GitHub Desktop.
RESTful controller spec examples
# This uses more real data and less mocking and stubbing for more direct and obvious code.
# It's probably easier to follow for people new to testing.
require 'spec_helper'
describe Notes::CommentsController do
let!(:commenter) { User.make! }
let!(:note) { Note.make! }
let(:comment) do
note.comments << Comment.make
note.comments.last
end
let!(:params) { { :note_id => note.id } }
let(:valid_attributes) { comment.attributes.slice *Comment.accessible_attributes }
let(:invalid_attributes) { { :body => nil } }
before(:each) { sign_in commenter }
shared_examples_for "any requested format" do
describe "GET edit" do
it "assigns the requested comment as @comment" do
get :edit, params.merge(:id => comment.id)
assigns(:comment).should eq(comment)
end
end
describe "POST create" do
context "with valid params" do
before(:each) { params.merge! :comment => valid_attributes }
it "creates a new Comment" do
expect { post :create, params }.to change {note.reload.comments.count}.by(1)
end
it "assigns a newly created comment as @comment" do
post :create, params
assigns(:comment).should be_a(Comment)
assigns(:comment).should be_persisted
end
it "sets current user as comment author" do
post :create, params
assigns(:comment).author.should eq(commenter)
end
end
context "with invalid params" do
before(:each) { params.merge! :comment => invalid_attributes }
it "does not create a new Comment" do
expect { post :create, params }.not_to change(note.comments, :count)
end
it "assigns a newly created but unsaved comment as @comment" do
post :create, params
assigns(:comment).should be_a_new(Comment)
end
end
end
describe "PUT update" do
context "with valid params" do
it "updates the requested comment" do
Comment.any_instance.should_receive(:update_attributes).with({'these' => 'params'})
put :update, params.merge(:id => comment.id, :comment => {'these' => 'params'})
end
it "assigns the requested comment as @comment" do
put :update, params.merge(:id => comment.id, :comment => valid_attributes)
assigns(:comment).should eq(comment)
end
end
context "with invalid params" do
before(:each) do
put :update, params.merge(:id => comment.id, :comment => invalid_attributes)
end
it "assigns the comment as @comment" do
assigns(:comment).should eq(comment)
end
end
end
describe "DELETE destroy" do
before(:each) { params.merge! :id => comment.id }
it "destroys the requested comment" do
expect { delete :destroy, params }.to change {note.reload.comments.count}.by(-1)
end
end
end
context "when HTML format requested" do
it_behaves_like "any requested format"
describe "GET show" do
it "returns 406 Not Acceptable" do
get :show, params.merge(:id => comment.id)
response.status.should be(406)
end
end
describe "POST create" do
context "with valid params" do
before(:each) { params.merge! :comment => valid_attributes }
it "redirects to the containing Note" do
post :create, params
response.should redirect_to user_note_path(note.owner, note)
end
it "sets flash message" do
post :create, params
flash[:notice].should match /comment has been added/i
end
end
end
describe "PUT update" do
context "with valid params" do
it "redirects to the containing Note" do
put :update, params.merge(:id => comment.id, :comment => valid_attributes)
response.should redirect_to [note.owner, note]
end
end
context "with invalid params" do
before(:each) do
put :update, params.merge(:id => comment.id, :comment => invalid_attributes)
end
it "re-renders the 'edit' template" do
response.should render_template(:action => 'edit')
end
end
end
describe "DELETE destroy" do
it "redirects to the containing Note" do
delete :destroy, params.merge(:id => comment.id)
response.should redirect_to [note.owner, note]
end
end
end
context "when JSON format requested" do
before(:each) { request.env["HTTP_ACCEPT"] = "application/json" }
it_behaves_like "any requested format"
describe "GET show" do
it "assigns the requested comment as @comment" do
get :show, params.merge(:id => comment.id)
assigns(:comment).should eq(comment)
end
end
describe "POST create" do
context "with valid params" do
it "returns 201 Created" do
post :create, params.merge(:comment => valid_attributes)
response.status.should be(201)
end
end
context "with invalid params" do
before(:each) { post :create, params.merge(:comment => invalid_attributes) }
it "returns 422 Unprocessable Entity" do
response.status.should be(422)
end
end
end
describe "PUT update" do
context "with valid params" do
it "returns 200 OK" do
put :update, params.merge(:id => comment.id, :comment => valid_attributes)
response.status.should be(200)
end
end
context "with invalid params" do
before(:each) do
put :update, params.merge(:id => comment.id, :comment => invalid_attributes)
end
it "returns 422 Unprocessable Entity" do
response.status.should be(422)
end
end
end
describe "DELETE destroy" do
it "returns 200 OK" do
delete :destroy, params.merge(:id => comment.id)
response.status.should be(200)
end
end
end
context "authentication" do
before(:each) do
sign_out commenter
request.env["HTTP_ACCEPT"] = "application/json"
end
it "is not required for GET show" do
get :show, params.merge(:id => comment.id)
response.should be_success
end
it "is required for volatile actions" do
put :update, params.merge(:id => comment.id, :comment => {})
response.status.should be(401)
post :create, params.merge(:comment => {})
response.status.should be(401)
delete :destroy, params.merge(:id => comment.id)
response.status.should be(401)
end
end
end
# This example uses heavier mocking/stubbing: more isolation of precisely what's
# being tested (and faster-running tests), but code is a bit harder to follow.
require 'spec_helper'
describe NotesController do
def mock_note(stubs={})
@mock_note ||= mock_model(Note, stubs).as_null_object
end
let(:user) { User.make! }
before(:each) do
sign_in user
controller.stub(:current_user) { user }
end
describe "with a user browsing his own Notes" do
before(:each) do
User.stub(:find).with(user.to_param).and_return(user)
end
describe "GET index" do
it "assigns user's notes as @notes" do
user.stub_chain(:notes, :desc) { paginatable_array [mock_note] }
get :index, :user_id => user.to_param
assigns(:notes).should eq([mock_note])
end
end
describe "GET show" do
it "assigns the requested note as @note" do
user.stub_chain(:notes, :find_by_slug).with("37") { mock_note }
get :show, :id => "37", :user_id => user.to_param
assigns(:note).should be(mock_note)
end
end
end
describe "with a user browsing another user's Notes" do
let(:browsed_user) { User.make! }
before(:each) do
User.stub(:find).with(browsed_user.to_param).and_return(browsed_user)
end
describe "GET index" do
it "assigns browsed user's notes as @notes" do
browsed_user.stub_chain(:notes, :desc) { paginatable_array [mock_note] }
get :index, :user_id => browsed_user.to_param
assigns(:notes).should eq([mock_note])
end
end
describe "GET show" do
it "assigns the requested note as @note" do
browsed_user.stub_chain(:notes, :find_by_slug).with("37") { mock_note }
get :show, :id => "37", :user_id => browsed_user.to_param
assigns(:note).should be(mock_note)
end
end
end
describe "GET new" do
it "assigns a new note as @note" do
user.stub_chain(:notes, :build) { mock_note }
get :new, :user_id => user.to_param
assigns(:note).should be(mock_note)
end
end
describe "GET edit" do
it "assigns the requested note as @note" do
user.stub_chain(:notes, :find_by_slug).with("37") { mock_note }
get :edit, :id => "37", :user_id => user.to_param
assigns(:note).should be(mock_note)
end
end
describe "POST create" do
describe "with valid params" do
it "assigns a newly created note as @note" do
user.stub_chain(:notes, :build).with({'these' => 'params'}) { mock_note(:save => true) }
post :create, :note => {'these' => 'params'}, :user_id => user.to_param
assigns(:note).should be(mock_note)
end
it "redirects to the created note" do
user.stub_chain(:notes, :build) { mock_note(:save => true) }
post :create, :note => {}, :user_id => user.to_param
response.should redirect_to(user_note_url(user, mock_note))
end
end
describe "with invalid params" do
it "assigns a newly created but unsaved note as @note" do
user.stub_chain(:notes, :build).with({'these' => 'params'}) { mock_note(:save => false) }
post :create, :note => {'these' => 'params'}, :user_id => user.to_param
assigns(:note).should be(mock_note)
end
it "re-renders the 'new' template" do
user.stub_chain(:notes, :build) { mock_note(:save => false) }
post :create, :note => {}, :user_id => user.to_param
response.should render_template(:action => "new")
end
end
end
describe "PUT update" do
describe "with valid params" do
it "updates the requested note" do
user.stub_chain(:notes, :find_by_slug).with("37") { mock_note }
mock_note.should_receive(:update_attributes).with({'these' => 'params'})
put :update, :id => "37", :note => {'these' => 'params'}, :user_id => user.to_param
end
it "assigns the requested note as @note" do
user.stub_chain(:notes, :find_by_slug) { mock_note(:update_attributes => true) }
put :update, :id => "1", :user_id => user.to_param
assigns(:note).should be(mock_note)
end
it "redirects to the note" do
user.stub_chain(:notes, :find_by_slug) { mock_note(:update_attributes => true) }
put :update, :id => "1", :user_id => user.to_param
response.should redirect_to(user_note_url(user, mock_note))
end
end
describe "with invalid params" do
it "assigns the note as @note" do
user.stub_chain(:notes, :find_by_slug) { mock_note(:update_attributes => false) }
put :update, :id => "1", :user_id => user.to_param
assigns(:note).should be(mock_note)
end
it "re-renders the 'edit' template" do
user.stub_chain(:notes, :find_by_slug) { mock_note(:update_attributes => false) }
put :update, :id => "1", :user_id => user.to_param
response.should render_template(:action => "edit")
end
end
end
describe "DELETE destroy" do
it "destroys the requested note" do
user.stub_chain(:notes, :find_by_slug).with("37") { mock_note }
mock_note.should_receive(:destroy)
delete :destroy, :id => "37", :user_id => user.to_param
end
it "redirects to the notes list" do
user.stub_chain(:notes, :find_by_slug) { mock_note }
delete :destroy, :id => "1", :user_id => user.to_param
response.should redirect_to(user_notes_url)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment