This below is spec/controllers/askings_controller_spec.rb.
require 'rails_helper'
RSpec.describe AskingsController, type: :controller do
describe 'Get #show' do
before do
#asking=create(:asking)
get :show , id: #asking.id
end
it 'should render show' do
expect(response).to render_template(:show)
end
it 'should Undertaking new' do
expect(assigns(:undertaking)).to be_a_new(Undertaking)
end
it 'should response status 200' do
expect(response.status).to eq(200)
end
end
end
And rspec result is below.
1) AskingsController Get #show should render show
Failure/Error: #asking=Asking.find(id: params[:id])
ActiveRecord::RecordNotFound:
Couldn't find Asking with 'id'={:id=>"2"}
2) AskingsController Get #show should Undertaking new
Failure/Error: #asking=Asking.find(id: params[:id])
ActiveRecord::RecordNotFound:
Couldn't find Asking with 'id'={:id=>"2"}
3) AskingsController Get #show should response status 200
Failure/Error: #asking=create(:asking)
ActiveRecord::RecordInvalid:
mailaddress exists.(<- I translate Japanese error.)
Why do I have this eeror?
I think that how to use 'create' is incorrect.
Please tell me the solution.
I tried to write some tests for the "show" action in Rails API
require 'rails_helper'
RSpec.describe AirlinesController, type: :controller do
describe "GET #show" do
before(:each) do
#airline = FactoryGirl.create(:airline)
get :show, id: #airline.id
end
it "should return the airline information" do
airline_response = json_response
expect(airline_response[:name]).to eql #airline.name
end
it {should respond_with :ok}
end
end
The test passed. However, when I try to use let and subject like this
require 'rails_helper'
RSpec.describe AirlinesController, type: :controller do
describe "GET #show" do
let(:airline) {FactoryGirl.create(:airline)}
subject {airline}
before(:each) do
get :show, id: airline.id
end
it "should return the airline information" do
airline_response = json_response
expect(airline_response[:name]).to eql airline.name
end
it {should respond_with :ok}
end
end
It showed "NoMethodError undefined method `response' for ..."
This makes me confused!
Don't set the subject. The subject of a controller spec is the controller, not a model object. Just remove the line that sets subject and you shouldn't get that error any more.
it {should respond_with :ok}
I assume this line takes the subject and makes a response call.
The recommended syntax is:
it "returns 200" do
expect(response).to be_success
end
Or maybe your json_response helper method is using subject.response instead of response.
I am attempting to create a RSpec controller test for a namespaced controller, but rspec doesn't seem able to detect the nesting and generate the proper path for the post :create action.
This is my spec code:
# for: /app/controllers/admin/crm/report_adjustments_controller.rb
require 'spec_helper'
describe Admin::Crm::ReportAdjustmentsController do
render_views
before(:each) do
signin
end
describe "GET 'index'" do
it "returns http success" do
get :index
response.should be_success
end
end
describe "POST 'create'" do
it "creates with right parameters" do
expect {
post :create, report_adjustment: {distributor_id: #ole_distributor.id, amount: "30.0", date: Date.today }
}.to change(Crm::ReportAdjustment, :count).by(1)
response.should be_success
end
end
end
# routes.rb
namespace :admin do
namespace :crm do
resources :report_adjustments
end
end
For this code, the get :index works just fine, but when post :create is called, the following error is generated: undefined method 'crm_report_adjustment_url'
Why would RSpec be smart enough to figure things out with get :index, but not with post :create? How do I get RSpec to properly load the right route, which is admin_crm_report_adjustments_url?
Thanks in advance.
Try posting to the url instead:
post admin_crm_report_adjustments_url
# or
post "/admin/crm/report_adjustments"
As I added tests to my spec, I became suspicious about every single one passing just as I wrote it, so I added some syntax errors into the code. It turned out, Rspec was not running my recent tests so the syntax errors weren't getting picked up. The comment in the code below shows the arbitrary line at which Rspec stopped showing a green period or red F for a test:
require 'spec_helper'
describe Api::PagesController do
def valid_session
{}
end
describe "GET index" do
before :each do
#page = create(:page)
end
it "assigns all pages as #pages" do
get :index
assigns(:pages).should eq([#page])
end
it "returns json" do
get :index, format: :json
expect(response.body).to have_content #page.to_json
end
end
describe "GET show" do
before :each do
#page = create(:page)
end
it "assigns the requested page as #page" do
get :show, {:id => #page.to_param}, valid_session
assigns(:page).should eq(#page)
end
it "returns json" do
get :show, {:id => #page.to_param}, valid_session, format: :json
expect(response.body).to have_content #page.to_json
end
end
describe "GET new" do
it "assigns a new page as #page" do
get :new, {}, valid_session
assigns(:page).should be_a_new(Page)
end
end
describe "GET edit" do
before :each do
#page = create(:page)
end
it "assigns the requested page as #page" do
get :edit, {:id => #page.to_param}, valid_session
assigns(:page).should eq(#page)
end
it "returns json" do
get :edit, {:id => #page.to_param}, valid_session, format: :json
expect(response.body).to have_content #page.to_json
end
end
describe "POST create" do
describe "with valid params" do
it "creates a new Page in the database" do
expect {
post :create, {page: attributes_for(:page)}, valid_session
}.to change(Page, :count).by(1)
end
it "assigns a newly created page as #page" do
post :create, {page: attributes_for(:page)}, valid_session
assigns(:page).should be_a(Page)
assigns(:page).should be_persisted
end
#################### TESTS BELOW HERE ARE NOT SHOWN BY RSPEC ##########
it "returns json" do
expect{
post :create, {page: attributes_for(:page)}, valid_session
}.to have_content page.to_json
end
end
describe "with invalid params" do
it "does not save the new page in the database" do
expect {
post :create, {page: attributes_for(:page_invalid)}, valid_session
}.to_not change(Page, :count).by(1)
end
#FUTURE TEST - redirects to new page with errors
end
end
describe "PUT update" do
before :each do
#page = create(:page)
end
describe "with valid params" do
it "updates the requested page" do
Page.any_instance.should_receive(:update_attributes).with({ "title" => "MyString" })
put :update, {:id => #page.to_param, :page => { "title" => "MyString" }}, valid_session
end
it "assigns the requested page as #page" do
put :update, {:id => #page.to_param, :page => { "title" => "MyString" }}, valid_session
assigns(:page).should eq(#page)
end
it "returns json" do
put :update, {:id => #page.to_param, :page => { "title" => "MyString" }}, valid_session, format: :jason
expect(response.body).to have_content #page.to_json
end
end
describe "with invalid params" do
it "assigns the page as #page" do
# Trigger the behavior that occurs when invalid params are submitted
Page.any_instance.stub(:save).and_return(false)
put :update, {:id => #page.to_param, page: attributes_for(:page_invalid)}, valid_session
assigns(:page).should eq(#page)
end
#FUTURE TEST - redirects to edit
end
end
describe "DELETE destroy" do
before :each do
#page = create(:page)
end
it "destroys the requested page" do
expect {
delete :destroy, {:id => #page.to_param}, valid_session
}.to change(Page, :count).by(-1)
end
end
describe "GET published" do
before :each do
#page = create(:page)
#page_unpublished = create(:page_unpublished)
end
it "returns a list of published pages only" do
get :published, format: :json
assigns(:pages).should eq([#page])
expect(response.body).to have_content #page_unpublished.to_json
end
end
describe "GET unpublished" do
before :each do
#page = create(:page)
#page_unpublished = create(:page_unpublished)
end
it "returns a list of unpublished pages only" do
get :unpublished, format: :json
assigns(:pages).should eq([#page_unpublished])
expect(response.body).to have_content #page_unpublished.to_json
end
end
describe "GET total_words" do
before :each do
#page = create(:page)
end
it "returns a list of unpublished pages only" do
get :total_words, {:id => #page.to_param}, format: :json
assigns(:total_words).should eq([#page_unpublished])
expect(response.body).to have_content #page_unpublished.to_json
end
end
end
When I intentionally added syntax errors to earlier tests, I saw red Fs instead of the green dots, but no error was being reported. Earlier, when there was an error, I'd see (for example):
16:10:14 - INFO - Running: spec/models/page_spec.rb
Running tests with args ["--drb", "-f", "progress", "-r", "/Users/user/.rvm/gems/ruby-1.9.3-p194/gems/guard-rspec-1.2.1/lib/guard/rspec/formatters/notification_rspec.rb", "-f", "Guard::RSpec::Formatter::NotificationRSpec", "--out", "/dev/null", "--failure-exit-code", "2", "spec/models/page_spec.rb"]...
.......F
Failures:
1) Page Publishing returns unpublished pages
Failure/Error: expect(Page.unpublished).to eq [page_unpublished]
NameError:
undefined local variable or method `page_unpublished' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_4:0x0000010355b8c0>
# ./spec/models/page_spec.rb:58:in `block (3 levels) in <top (required)>'
Finished in 0.54212 seconds
8 examples, 1 failure
Failed examples:
rspec ./spec/models/page_spec.rb:57 # Page Publishing returns unpublished pages
Done.
Now, when a test fails, I only see:
17:55:26 - INFO - Running: spec/controllers/pages_controller_spec.rb
Running tests with args ["--drb", "-f", "progress", "-r", "/Users/user/.rvm/gems/ruby-1.9.3-p194/gems/guard-rspec-1.2.1/lib/guard/rspec/formatters/notification_rspec.rb", "-f", "Guard::RSpec::Formatter::NotificationRSpec", "--out", "/dev/null", "--failure-exit-code", "2", "spec/controllers/pages_controller_spec.rb"]...
.....FF..Done.
This change happened at a pretty arbitrary time while coding, I didn't modify the Guardfile or any Spork configuration details. Any idea why this is happening?
It looks like one of the arguments to rspec is --out /dev/null. So your output is being redirected from STDOUT.
One possibility is that this is being caused by one or more bad tests. Have you tried commenting out various tests to see if you can isolate the problematic ones? If you're running your tests in order, I'd start with the ones just before and after the point at which rspec exits prematurely.
I have 2 simple RSpec tests i've written for a small rails app i've done to learn rails. I originally had a mock setup for my Link class but was getting the same issue.
This is my test code:
require 'spec_helper'
describe LinksController do
render_views
before(:each) do
link = Link.new
link.stub!(:title).and_return("Reddit")
link.stub!(:url).and_return("http://www.reddit.com")
link.stub!(:created_at).and_return(Time.now)
link.stub!(:updated_at).and_return(Time.now)
link.stub!(:user_id).and_return("1")
link.stub!(:id).and_return("1")
link.save
user = User.new
user.save
end
it "renders the index view" do
get :index
response.should render_template('links/index')
response.should render_template('shared/_nav')
response.should render_template('layouts/application')
end
it "renders the show view" do
get :show, :id => 1
response.should render_template('links/show')
response.should render_template('shared/_nav')
response.should render_template('layouts/application')
end
end
I'm new to both rails and RSpec, not sure what I should be doing to get this to work. What is the best way to test this show method from my LinksController when you need data? I tried mock_model too but maybe I was using it wrong.
You can see all the app code on Github
The problem is that you are stubbing a model, so it's not stored in the database. That means that when you call get :show, :id => 1 the query to the database returns nothing and your tests fail. Stubbing is great when you want to fake a response or an object without using the database, but if you are depending on actual Rails code that uses the database you can't use this method because nothing exists in the database. To fix this I would drop the stubbed models entirely and actually create them.
require 'spec_helper'
describe LinksController do
render_views
before(:each) do
user = User.create
#link = Link.create :title => "Reddit",
:url => "http://www.reddit.com",
:user => user
end
it "renders the index view" do
get :index
response.should render_template('links/index')
response.should render_template('shared/_nav')
response.should render_template('layouts/application')
end
it "renders the show view" do
get :show, :id => #link.id
response.should render_template('links/show')
response.should render_template('shared/_nav')
response.should render_template('layouts/application')
end
end
You should also eventually look into Factory gems like Sham and Factory Girl to simplify the creation of test data.