Rspec controller show test failing with rails 3.2.6 - ruby-on-rails

I have a simple rspec test which is failing after I upgrade to 3.2.6.
Here is the spec in users_controller_spec.rb
describe "show action" do
before(:each) do
User.stub!(:find).with(#user.id).and_return(#user)
end
def do_get
get :show, :id => #user.id
end
it "should be successful" do
do_get
response.should be_success
end
end
and here is the error
1) UsersController show action should be successful
Failure/Error: get :show, :id => #user.id
.........................
(class)> received :find with unexpected arguments
expected: (2)
got: ("2")
Not sure where is going wrong. The show action has nothing in the controller, it is just
def show
end

Related

'undefined method' post with Rails and Rspec

Got stuck with:
' undefined method `post' for #<Class:0x000001058c0f68> (NoMethodError)'
on testing controller create action.
I'm using Rails 4, rpsec, and Factory Girl
Controller:
def create
#post = Post.new(post_params)
#post.user_id = current_user.id
if #post.save
flash[:success] = "Yay! Post created!"
redirect_to root_path
else
# flash[:error] = #post.errors.full_messages
render 'new'
end
end
Test:
describe '#create' do
post 'create', FactoryGirl.attributes_for(:post, user: #user)
response.should be_successful
end
I think post method is accessible inside it method block:
describe 'create' do
it 'should be successful' do
post :create, FactoryGirl.attributes_for(:post, user: #user)
response.should be_success
end
end
BTW I think you need to test for redirect, not success status.
Sorry for being off-topic but I just want to give you some advice.
Consider following best practices and use RSpec's expect syntax instead of should. Read more about why the should syntax is a bad idea here: http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
This is how I would rewrite your example:
describe 'create' do
it 'responds with 201' do
post :create, attributes_for(:post, user: #user)
expect(response.status).to eq(201)
end
end
In the example I'm using FactoryGirl's short syntax method attributes_for instead of FactoryGirl.attributes_for, it saves a few bytes. Here's how to make the short methods available (in spec/test_helper.rb):
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
end
I'm testing for the status code 201 which Rails will return by default for a successful create action (redirect should be 3xx).This makes the test more specific.
Hope it's any help for writing better specs.
The issue comes from the fact that post should be used inside an it statement. I usually test my controllers like this:
describe 'POST "create"' do
let(:user) { User.new }
let(:params) { FactoryGirl.attributes_for(:post, user: user) }
let(:action) { post :create, params }
let!(:post) { Post.new }
before do
Post.should_receive(:new).and_return(post)
end
context 'on success' do
before do
post.should_receive(:save).and_return(true)
end
it 'renders success' do
action
expect(response).to be_success
end
it 'redirects' do
action
expect(response).to be_redirected
end
it 'sets flash message' do
action
expect(flash[:success]).to_not be_empty
end
end
context 'on failure' do
before do
post.should_receive(:save).and_return(false)
end
it 'renders new' do
action
expect(response).to render_template(:new)
end
end
end

Rspec POST controller create test fails but web based submission works

I have the following rspec test for create method in my
describe "with valid information" do
it "should respond with success" do
post 'create', :show_secretary_id => #show_secretary.id, :show => #show
response.should be_success
end
it "should incremenet the show count" do
expect do
post 'create', :show_secretary_id => #show_secretary.id, :show => #show
end.to change(Show,'count').by(1)
end
end
The test fails. However, when I try the create method in the browser, it works. Any ideas on what I am missing?
EDIT: My Controller Code
def create
#show_secretary = ShowSecretary.find_by_id(params[:show_secretary_id])
#show = #show_secretary.shows.build(params[:show])
if #show.save
flash[:notice] = "Successfully created show"
redirect_to show_path #show
else
render 'new'
end
end
EDIT: #show_secretary, #show
These two objects are ActiveRecords created and built by FactoryGirl respectively.
#show_secretary = FactoryGirl.create(:show_secretary_user).verifiable
#show = FactoryGirl.build(:show)
Replace
#show = FactoryGirl.build(:show)
with:
#show = FactoryGirl.attributes_for(:show)

rspec error with create in controller

Here is the error in rspec:
CategoriesController GET 'update' should be successful
Failure/Error: get 'update'
ActiveRecord::RecordNotFound:
Couldn't find Category without an ID
# c:in `find'
# ./app/controllers/categories_controller.rb:45:in `update'
# ./spec/controllers/categories_controller_spec.rb:35:in `block (3 levels) in <top (required)>'
Here is the code in controller:
def edit
#category = Category.find(params[:id])
end
def update
#category = Category.find(params[:id])
##category.reload. caused nil.reload error
if #category.update_attributes(params[:category], :as => :roles_update)
#category = Category.find(params[:id])
redirect_to #category, :notice => 'Category was successfully updated'
else
#categories = Category.all
render 'index'
end
end
Here is the rspec code:
describe "GET 'update'" do
it "should be successful" do
get 'update'
response.should be_success
end
end
Any thoughts? Thanks.
You pasted the create action instead of the update action. Also, you are trying to test the update action with a get request.. it should be with a put request if you are following the conventions.
If you had, say, the update action implemented... you would test more or less like:
describe CategoriesController do
let(:category) { mock_model(Category).as_null_object }
describe "PUT update" do
before do
Category.should_receive(:find).with(5).and_return(category)
end
context "when a category updates succesfully" do
before do
category.stub(:update_attributes).and_return(true)
end
it "redirects to the categories page" do
put :update, :id => 5, :category => { :some_val => 4 }
response.should redirect_to(categories_path)
end
it "sets the flash message" do
put :update, :id => 5, :category => { :some_val => 4 }
flash[:notice].should eq("Category was succesfully updated")
end
end
context "when a category does not update successfully" do
before do
category.stub(:update_attributes).and_return(false)
end
it "sets the flash message"
it "redirects to the categories page"
# etc etc
end
end
end
To get to this point (meaning the addition of mock models, stubs, what have you) you would normally start "fresh" so to speak and work your way up TDD style. Hope it helps

Rspec testing templates being rendered

Im trying to test a condition where on successful signup a Success Template is rendered by the following controller code
def create
#user = User.new(params[:user])
if #user.save
render :template => "success"
else
flash[:notice] = "Oops Somethings not quite right! :("
render :action => "new"
end
end
I am using the following spec to test out this code
before(:each) do
#user = User.new
#user.attributes = valid_attributes
#params = valid_attributes
#user.stub!(:save).and_return(true)
end
def do_post
post :create
end
it "should create new user " do
count = User.count
do_post
user = User.new(#params)
user.save.should eql(true)
User.count.should eql(count + 1)
end
it "should render the success page on successful signup" do
do_post
#user.save
response.should render_template("success") if #user.save
end
But the example fails "it should render success page on successful signup" with this error message
1)
'UsersController handling POST /users should render the success page on successful signup' FAILED
expected "success", got "users/new.html.erb"
./spec/controllers/users_controller_spec.rb:67:
The success view is an template stored in the views/users/ without an action. Im guessing im making a very fundamental mistake and would like some help .
You are stubbing the #user variable in the test, but the controller will instantiate a new instance so the stub won't be in place.
It's not a good idea to use a stub in this case just to emulate a successful save call. Why don't you supply valid data instead and make sure the action is successful?
The following code is for RSpec > 2.1 and it uses the expect syntax.
before(:each) do
#params = valid_attributes
end
it "should create new user" do
#_before = User.count
post :create, :user => #params
expect(assigns(:user)).to_not be_new_record
expect(User.count).to eq(#_before + 1)
end
it "should render the success page on successful signup" do
post :create, :user => #params
expect(response).to be_successful
expect(response).to render_template("success")
end
Finally, change
render :template => "success"
to
render :action => "success"
For previous RSpec versions or if you have to use the should syntax, use
before(:each) do
#params = valid_attributes
end
it "should create new user" do
#_before = User.count
post :create, :user => #params
assigns(:user).should_not be_new_record
User.count.should == (#_before + 1)
end
it "should render the success page on successful signup" do
post :create, :user => #params
response.should be_successful
response.should render_template("success")
end

How can I test ActiveRecord::RecordNotFound in my rails app?

I have this code in my controller and want to test this code line with a functional test.
raise ActiveRecord::RecordNotFound if #post.nil?
which assert method should I use?
I use the built-in rails 2.3.5 test framework.
I tried it with this code:
test "should return 404 if page doesn't exist." do
get :show, :url => ["nothing", "here"]
assert_response :missing
end
but it doesn't work for me. Got this test output:
test_should_return_404_if_page_doesn't_exist.(PageControllerTest):
ActiveRecord::RecordNotFound: ActiveRecord::RecordNotFound
app/controllers/page_controller.rb:7:in `show'
/test/functional/page_controller_test.rb:21:in `test_should_return_404_if_page_doesn't_exist.'
There are two things you can do. The first is to let ActionController provide the default action when it rescues ActiveRecord::RecordNotFound:
class PostsControllerTest < ActionController::TestCase
test "raises RecordNotFound when not found" do
assert_raises(ActiveRecord::RecordNotFound) do
get :show, :id => 1234
end
end
end
Using this method, you can't assert what gets rendered. You have to trust Rails/ActionController not to change behaviour.
An alternative, which I've sometimes used, is this:
class PostsControllerTest < ActionController::TestCase
test "renders post_missing page, and returns 404" do
get :show, params: { :id => 1234 }
assert_response :not_found
assert_template "post_missing"
end
end
class PostsController < ApplicationController
def show
#post = current_user.posts.find_by!(slug: params[:slug])
end
rescue_from ActiveRecord::RecordNotFound do
render :action => "post_missing", :status => :not_found
end
end
You should read more about #rescue_from on the ActiveSupport API.
For simplicity, I usually go with my 1st solution though.

Resources