I am writing the specs (with RSpec) for my API controller. When I test the GET request for the index everything works well, it returns the expected body and successful response, however, when I test the GET request for the show action it raises the following error:
ActionController::UrlGenerationError:
No route matches {:action=>"show", :controller=>"api/v1/contacts"}
Here is the code that I have written in my spec file:
require 'rails_helper' RSpec.describe Api::V1::ContactsController do describe "GET #index" do context 'with a successful request' do before do get :index end it "returns http success" do expect(response).to have_http_status(:success) expect(response.status).to eq(200) end it "JSON body response contains expected recipe attributes" do json_response = JSON.parse(response.body) expect(json_response.keys).to match_array(%w[data included]) end end end describe "GET #show" do context 'with a successful request' do before do get :show end it "returns http success" do expect(response).to have_http_status(:success) expect(response.status).to eq(200) end end end end
Here is the show route that the command rails routes
prints
Can someone help me see what am I missing? How can I test the GET request for the show action with RSpec?
The error is caused by the fact that you are not passing the slug parameter required by your route:
get :show, slug: contact.slug
But what you actually want here in the first place is a request spec and not a controller spec. A request spec sends actual HTTP requests to your application. Controller specs mock out most of the framework and let the bugs march right though - especially routing bugs.
The use of controller specs is discouraged by the the Rails and RSpec teams and should not be used outside of legacy code.
# spec/requests/api/v1/contacts_spec.rb
require 'rails_helper'
RSpec.describe 'API V1 Contacts', type: :request do
# This can be DRY:ed into a shared context
let(:json){ JSON.parse(response.body) }
subject { response }
# This example uses FactoryBot
# https://github.com/thoughtbot/factory_bot
let(:contact) { FactoryBot.create(:contact) }
# but you could also use a fixture
let(:contact){ contacts[:one] }
# describe the actual API and not how its implemented
describe "GET '/api/v1/contacts'" do
before { get api_vi_contacts_path }
it { is_expected.to be_successful }
it "has the correct response attributes" do
expect(json.keys).to match_array(%w[data included])
end
end
describe "GET '/api/v1/contacts/:id'" do
before { get api_vi_contact_path(contact) }
it { is_expected.to be_successful }
# @todo write examples about the JSON
end
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.