Undefined method response when using let and subject in RSpec - ruby-on-rails

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.

Related

RSpec test not passing: Expected response to be a <3XX: redirect>, but was a <200: OK>

I have set the following test in my ads_controller.spec.rb file:
describe "ads#create action" do
it "redirects to ads#show" do
#ad = FactoryBot.create(:ad)
expect(response).to redirect_to ad_path(#ad)
end
end
to correspond to this action in my ads controller:
def create
#ad = current_user.ads.create(ad_params)
redirect_to ad_path(#ad)
end
Once an ad is created, I want it to redirect to the show page for the just created ad. While this works in my browser, I clearly haven't structured my test right since I get the following error:
Failure/Error: expect(response).to redirect_to ad_path(#ad)
Expected response to be a <3XX: redirect>, but was a <200: OK>
I've tried to troubleshoot it for a while and not sure where I'm messing things up? Any ideas? Thanks!
You're not actually making a call to your create action. You have...
describe "ads#create action" do
it "redirects to ads#show" do
#ad = FactoryBot.create(:ad)
expect(response).to redirect_to ad_path(#ad)
end
end
Which is just using FactoryBot to create the ad. You need to do actual call to the post action.
RSpec.describe AdsController, type: :controller do
let(:valid_attributes) {
("Add a hash of attributes valid for your ad")
}
describe "POST #create" do
context "with valid params" do
it "redirects to the created ad" do
post :create, params: {ad: valid_attributes}
expect(response).to redirect_to(Ad.last)
end
end
end
end

Rspec Controller test not passing

My controller and my test file are bellow.
controllers/reports_controller.rb:
def index
#reports = Report.all
end
specs/controllers/reports_controller_spec.rb:
RSpec.describe ReportsController, type: :controller do
let(:test_report) {
2.times.map {
create(:report, student: create(:student), report_options_attributes: [
{option: create(:option), note: "ole" }
])
}
}
describe "GET #index" do
before(:each) do
get :index
end
it "should be success" do
expect(response).to be_success
end
it "should render index template" do
expect(response).to render_template(:index)
end
it "should load all reports" do
expect(assigns(:report)).to match_array test_report
end
end
The last test is not working, but it should work. What is wrong with it?
index test is empty..you need to assert something to pass.
can you add.. assert_response :success in index function.
Your var is different from the controller. Use reports instead of report like this:
it "should load all reports" do
expect(assigns(:reports)).to match_array test_report
end
It should work.

Rspec Error.(Couldn't find Asking with)

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.

Testing a before filter in rails controller

I seem to be stuck. I am trying to shore up some rspec testing and want to make sure the the correct before_filter methods are getting called for controllers. However, I am getting feedback saying the method never gets called.
The error:
Failure/Error: expect(controller).to receive(:authorize)
(#<UsersController:0x007fca2fd27110>).authorize(*(any args))
expected: 1 time with any arguments
received: 0 times with any arguments
The spec:
require "rails_helper"
RSpec.describe UsersController, :type => :controller do
let(:school){ FactoryGirl.create :school }
let(:user){ FactoryGirl.create :teacher}
before(:each){
allow(controller).to receive(:current_user).and_return(user)
school.teachers << user
}
context "Get #show" do
before(:each){ get :show, school_id: school.id, id: user.id }
it "responds successfully with an HTTP 200 status code" do
expect(controller).to receive(:authorize)
expect(response).to have_http_status(200)
end
it "renders the show template" do
expect(response).to render_template("show")
end
end
end
The controller:
class UsersController < ApplicationController
before_filter :authorize
def show
#user = User.find_by_id params[:id]
#school = #user.school
#coordinators = #school.coordinators
#teachers = #school.teachers
#speducators = #school.speducators
#students = #school.students
end
end
Manual testing shows that before is being called, and when I put a p in the authorize method it is called when I run the test, any thoughts on where the test is going wrong?
You must set method expectation before actual call, so your test should look like:
context "Get #show" do
subject { get :show, school_id: school.id, id: user.id }
it "calls +authorize+ befor action" do
expect(controller).to receive(:authorize)
subject
end
end
Check the documentation https://github.com/rspec/rspec-mocks#message-expectations

render_views helper not working as expected

I have a following method in my controller:
def create
#job = Job.new(job_params)
if #job.save
render 'create_success', status: :created
else
render 'create_failure', status: :bad_request
end
end
And here are my controller specs for this:
require 'rails_helper'
RSpec.describe Api::V1::JobsController, :type => :controller do
let(:actor) { FactoryGirl.create(:user, :service_advisor) }
let(:auth_token) { actor.authentication_token }
describe 'POST #create' do
render_views
context 'with invalid attrubutes' do
let(:job) { FactoryGirl.build(:job, customer_id: nil).attributes }
it 'renders create_failure view' do
expect(response).to render_template :create_failure
end
it 'returns 400 status code' do
expect(response.status).to eq 400
end
end
end
end
However, for some reason, no matter what i do, the controller spec allways thinks that this method returns empty response and status 200. I can test that method using postman or curl and it works as expected - return error messages and status codes (201/400) but my spec allways sees it as empty response with 200 status code.
It seems that render_views is not working. My env is:
ruby 2.0.0p594
Rails 4.1.0
rspec 3.1.5
You have not given call to create action in your test case.
it 'renders create_failure view' do
post :create, job
expect(response).to render_template :create_failure
end

Resources