Rspec Error.(Couldn't find Asking with) - ruby-on-rails

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.

Related

Rspec test fails due to to redirection to a page for loggin in (Rails + Devise + Cancancan)

I am writing test for controllers in Rails:
require 'rails_helper'
RSpec.describe GoodsController, type: :controller do
DatabaseCleaner.clean
user = User.create(password: "12345678")
user.save!
describe "GET index" do
it "renders the index template" do
sign_in user
get "index"
expect(response).to render_template("index")
end
end
DatabaseCleaner.clean
end
the GoodsController has this index action I want to test:
def index
if params[:category_id] == nil
#goods = Good.all
else
#goods = Good.where(category_id: params[:category_id])
end
end
and when I run the test, I receive this error:
1) GoodsController GET index renders the index template
Failure/Error: expect(response).to render_template("index")
expecting <"index"> but was a redirect to <http://test.host/users/sign_in>
# ./spec/controllers/goods_controller_spec.rb:12:in `block (3 levels) in <top (required)>'
I've added that sign_in user line, according to other answers in SO, but it didn't help. It still redirects to the logging page. How do I resolve this?
The user you create is not used by rspec when running the Examples (aka tests). It's just a variable inside a block that doesn't do anything useful.
When dealing with fixtures/factories you should either create them in before, let or inside the test itself (it block).
describe "GET index" do
let(:user) { User.create(password: "12345678") }
it "renders the index template" do
# OR, create it here before sign_in
sign_in user
get "index"
expect(response).to render_template("index")
end
end
Not sure if you are using factory_bot, but you should look at it. Usually DatabaseCleaner is set up inside rails_helper, check this SO post for more details.
If you are going to have multiple tests that need the user to be signed in you could also wrap the sign_in in a before hook.
describe "GET index" do
let(:user) { User.create(password: "12345678") }
before do
sign_in user
end
it "renders the index template" do
get "index"
expect(response).to render_template("index")
end
end

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

Undefined method response when using let and subject in RSpec

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.

RSpec - Functional Test - Syntax Check

so I'm writing a Test for my UserController, and the associated Devise dependency.
I'm trying to write a test that verify's userA can't access the show page of userB, but is redirected to the root_path instead. I'm guessing syntax errors are my issue, but I'd love another pair of eyes on it!
require 'rails_helper'
describe UsersController, :type => :controller do
# create test user
before do
#userA = User.create!(email: "test#example.com", password: "1234567890")
#userB = User.create!(email: "test2#example.com", password: "1234567890")
end
describe "GET #show" do
before do
sign_in(#userA)
end
context "Loads correct user details" do
get :show
expect(response).to have_http_status(200)
expect(assigns(:user)).to eq #userA
end
context "No user is logged in" do
it "redirects to login" do
get :show, id: #userA.id
expect(response).to redirect_to(root_path)
end
end
end
describe "GET Unauthorized page" do
before do
sign_in(#userA)
end
context "Attempt to access show page of UserB" do
it "redirects to login" do
get :show, id: #userB.id
expect(response).to have_http_status(401)
expect(response).to redirect_to(root_path)
end
end
end
end
You're missing an "it" block in
context "Loads correct user details" do
get :show
expect(response).to have_http_status(200)
expect(assigns(:user)).to eq #userA
end

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

Resources