Luke
Luke

Reputation: 598

Rails route is not found in the tests

This application is a Rails 4 app and just an API (at this point). I can hit my URL from the browser, but when I try to access it in a test it can't find the URL. I get this:

No route matches {:action=>"/api/v1/users/20", :controller=>"api/v1/users"}

There are not any assertions in my test yet. Just trying to get past this error first:

# /spec/controllers/api/v1/users_controller_spec.rb
require 'rails_helper'

RSpec.describe Api::V1::UsersController, :type => :controller do
  describe "User API" do
    it "can return a user by ID" do
      user = FactoryGirl.create(:user)

      get "/api/v1/users/#{user.id}"
    end
  end
end

And my controller:

# app/controllers/api/v1/users_controller.rb
class Api::V1::UsersController < ApplicationController
  before_action :set_user, only: [:show]

  def show 
  end

  private

  def set_user
    @user = User.find(params[:id])
  end
end

Any my routes:

# config/routes.rb
Rails.application.routes.draw do
  namespace :api, defaults: {format: 'json'} do
    namespace :v1 do
      resources :users, only: [:show]
    end
  end
end

And rake routes give me:

     Prefix Verb URI Pattern                 Controller#Action
api_v1_user GET  /api/v1/users/:id(.:format) api/v1/users#show {:format=>"json"}

And my gems:

group :test do
  gem 'capybara'
end

group :development, :test do
  gem 'rspec-rails'
  gem 'factory_girl_rails'
  gem 'database_cleaner'
end

I'm sure there is something simple I am missing here, but I've spent a couple hours and can't figure it out.

Upvotes: 1

Views: 1073

Answers (2)

Luke
Luke

Reputation: 598

I think I finally figured this out... to some extent. I think because this is a unit test, I need to pass get the action name instead of the URL. Now I have this and it is working:

RSpec.describe Api::V1::UsersController, :type => :controller do
  describe "User API" do
    it "can return a user by ID" do
      user = FactoryGirl.create(:user)

      # get "/api/v1/users/#{user.id}"       # This failed.
      get :show, id: user.id, format: 'json' # This works!

    end
  end
end

I do want to test to make sure that URL's are not changing. I guess that's more like an integration test, so I think I'll probably do that in the features directory and do it the way that @NickM mentioned.

Update

I'm writing an API app. After fixing the above I was getting a missing template error. I had to change my get method to also have a format parameter.

Upvotes: 0

NM Pennypacker
NM Pennypacker

Reputation: 6942

You could try using Capybara's visit method instead of get. In /spec/controllers/api/v1/users_controller_spec.rb

require 'rails_helper'
require 'capybara' # unless you're already doing this in spec_helper.rb

RSpec.describe Api::V1::UsersController, :type => :controller do
  describe "User API" do
    it "can return a user by ID" do
      user = FactoryGirl.create(:user)

      visit "/api/v1/users/#{user.id}"
    end
  end
end

Upvotes: 1

Related Questions