No Route Found in Rspec Test for an Existing Route

No route found in rspec test for an existing route

It looks like you are writing a controller spec (which rails calls functional tests)

In these tests the get, post etc methods expect the first argument to be the name of the action and the second a hash of options - they bypass routing (although they do check that the action is routable). You would instead do

get :show, id: e.id

In integration tests (request specs or feature specs) on the other hand you would use an actual path (and depending on the setup you would use either visit or get, post etc but they'd be different get methods)

RSpec no route matches and file does not exist

Ok, so the error that is causing every spec to fail is that uploaded image. It can't find the image file that you are trying to upload. Where is that image file actually located? Create that file and put it in the right place and they should start working again.

As to the routing-spec - that's the error that you included in your question, and it'll be localised to your routing-spec only (spec/routing/comments_routing_spec.rb according to your paste-bin), and will be fixed by just adjusting the routes to be the nested ones. They should include everything necessary to make the routes work (including a valid post-id).

Secondly, it should be something like:

expect(:delete => "/posts/1/comments/1").to route_to("comments#destroy", :id => "1", :post_id => "1")

Note: personally I don't bother with route-specs for simple resources, just for complex ones, but you may prefer it as a backup while you're getting used to Rails.

Why got Rspec No route matches error with Rails?

Edit: After looking at provided routes I think that main problem might be that you namespaced controller but not resource in routes, if that is the problem you will find solution below with some other suggestions.


Make sure you have a routing properly set in routes.rb in your case you should have something like:

namespace :iot do
resources :hardwares
end

Then you will need to specify path instead of method name in your get request inside RSpec example:

get "/iot/hardwares", params { "test": 1 }

Let's say we have a BooksController with index action. In our routes.rb file there is resources: :books.

Provided that routes are setup correctly your example looking like this should work:

require 'rails_helper'

RSpec.describe Iot::HardwaresController, type: :controller do
describe "GET #index" do
context "with invalid params" do
it "renders a JSON response with errors" do
get "/iot/hardwares", params: { "test": 1 }
expect(response).to have_http_status(:bad_request)
end
end
end
end

To make it even better you could extract path to let variable as you will be probably using it for more examples. Like this:
require 'rails_helper'

RSpec.describe Iot::HardwaresController, type: :controller do
describe "GET #index" do
let(:path) { "/iot/hardwares" }

context "with invalid params" do
it "renders a JSON response with errors" do
get path, params: { "test": 1 }
expect(response).to have_http_status(:bad_request)
end
end
end
end

Also you could consider changing your specs to be request specs instead of controller specs. In the release notes of RSpec you can find:

For new Rails apps: we don't recommend adding the rails-controller-testing gem to your application. The official recommendation of the Rails team and the RSpec core team is to write request specs instead. Request specs allow you to focus on a single controller action, but unlike controller tests involve the router, the middleware stack, and both rack requests and responses. This adds realism to the test that you are writing, and helps avoid many of the issues that are common in controller specs. In Rails 5, request specs are significantly faster than either request or controller specs were in rails 4, thanks to the work by Eileen Uchitelle1 of the Rails Committer Team.

You can read more on this here: http://rspec.info/blog/2016/07/rspec-3-5-has-been-released/

No route matches delete in Rspec despite route existing in controller

For those struggling with any similar issue. The fault with this lay with my nested /api/v1 folder structure which as suggested by Max above caused the somewhat ugly api_v1_users_url(user). This originated through my using scaffolding rather than adding the files manually.

It seems rails uses the full path to the controller to construct objects and associated variables.

I refactored all the class declarations and rspec file paths as below.

This appears to have resolved the initial code smells mentioned in teh comments as well as the initial issue.

➜  api git:(authentication) ✗ tree spec 
spec
├── factories
│   └── users.rb
├── models
├── rails_helper.rb
├── requests
│   └── api
│   └── users_spec.rb
├── routing
│   └── users_routing_spec.rb
├── spec_helper.rb
└── support
└── factory_bot.rb

➜ api git:(authentication) ✗ tree app
app
├── channels
│   └── application_cable
│   ├── channel.rb
│   └── connection.rb
├── controllers
│   ├── application_controller.rb
│   ├── concerns
│   └── users_controller.rb
├── jobs
│   └── application_job.rb
├── mailers
│   └── application_mailer.rb
├── models
│   ├── concerns
│   └── user.rb
└── views
└── layouts
├── mailer.html.erb
└── mailer.text.erb

The corrected Rspec tests generally now look like this:

  describe "DELETE /destroy" do
it "destroys the requested user" do
user = User.create! valid_attributes
expect {
delete user_url(user),headers: valid_headers, as: :json
}.to change(User, :count).by(-1)
end
end

Removing the nested declarations:

user = Api::V1::User.create! valid_attributes

Rspec request specs: No routes match

A good night sleep really does help. I woke up; took another look at the problem and realized the culprit.

  • Main issue was that in spec/requests/api/v1/books_spec.rb host was set to api.localhost.com (localhost.com; really?) when it should be api.localhost:3000.
  • Second issue was forgetting to set the correct value for config.action_dispatch.tld_length in test; I did in dev but forgot to do so in test.


Related Topics



Leave a reply



Submit