Trace Rspec's get request routing in controller action spec - ruby-on-rails

I am trying to test a simple controller action in a moduled controller. However, my get :index request returns a 404, instead of a 200 response. Is there a way to trace the routing of this get request?
require "spec_helper"
describe Admin::WidgetsController do
describe "GET index" do
it "has a 200 status code" do
get :index
response.code.should eq("200")
end
end
end
The controller looks like as you would expect:
class Admin::WidgetsController < Admin::ApplicationController
respond_to :html, :xml, :json
def index
respond_with(#content = "content")
end
end

Sounds like something is wrong with your routing. On the console you can run this to see what routes are available to your app:
$> rake routes
I'm pretty sure the following, when it fails, will show you what it's being redirected to
describe Admin::WidgetsController do
describe "GET index" do
it "has a 200 status code" do
get :index
response.should redirect_to(:action => 'other_action')
end
end
end
You can check out these links for more info:
http://guides.rubyonrails.org/routing.html
http://old.rspec.info/rails/writing/controllers.html

Related

RSpec 404 test respond with status 200

I've written a test to test the 404 page
pages_controller_spec.rb
RSpec.describe PagesController, type: :controller do
before :all do
Rails.application.config.action_dispatch.show_exceptions = true
Rails.application.config.consider_all_request_local = false
end
describe "status 404" do
it "respond with 404 if page is not found" do
get :help, params: { id: "foobar" }
expect(response.status).to eq(404)
end
end
end
The pages controller is simple and functions to render the static pages "/help" and "/about"
class PagesController < ApplicationController
def help
end
def about
end
end
The error handling is set up as follows
application_controller.rb
def not_found
raise ActionController::RoutingError.new("Not Found")
rescue
render_404
end
def render_404
render file: "#{Rails.root}/public/404", status: :not_found
end
The test result is
expected: 404
got: 200
Which I do not understand since "/help/foobar" does render the 404 page when I try it myself in the browser. I guess the problem could be that my "get" action in the test is formatted wrong but I'm not sure.
EDIT
config/routes.rb as requested
get "/about", to: "pages#about"
get "/help", to: "pages#help"
EDIT 2
Updated the test with the syntax from https://relishapp.com/rspec/rspec-rails/v/3-4/docs/routing-specs/route-to-matcher
The test now looks like this
RSpec.describe PagesController, type: :controller do
before :all do
Rails.application.config.action_dispatch.show_exceptions = true
Rails.application.config.consider_all_request_local = false
end
describe "status 404" do
it "respond with 404 if page is not found" do
expect(get("/foobar")).to route_to("application#not_found")
end
end
end
Unfortuenly this raises another error
ActionController::UrlGenerationError:
No route matches {:action=>"/foobar", :controller=>"pages"}
No route is matching which is kind of the point but the "not_found" method is being used for some reason
Change your routes to make your call work from the browser:
get "/help/:id", to: "pages#help"
If the test returns a 200, it's because it calls directly the help method from your controller without using the config/routes.rb file.
EDIT
Here is how you test your routing: https://relishapp.com/rspec/rspec-rails/v/3-4/docs/routing-specs/route-to-matcher

How to create a route for testing purposes?

I'm writing tests with rspec for my application controller in my rails app (written in Rails 4) and I'm running into a problem where it doesn't recognize the route for the HTTP request I'm sending. I know there's a way to do this using MyApp::Application.routes but I'm not able to get it working.
#application_controller_spec.rb
require 'spec_helper'
class TestController < ApplicationController
def index; end
end
describe TestController do
before(:each) do
#first_user = FactoryGirl.create(:user)
# this is to ensure that all before_filters are run
controller.stub(:first_time_user)
controller.stub(:current_user)
end
describe 'first_time_user' do
before(:each) do
controller.unstub(:first_time_user)
end
context 'is in db' do
before(:each) do
#user = FactoryGirl.create(:user)
controller.stub(:current_user).and_return(#user)
end
it 'should not redirect' do
get :index
response.should_not be_redirect
end
end
context 'is not in db' do
context 'session[:cas_user] does not exist' do
it 'should return nil' do
get :index
expect(assigns(:current_user)).to eq(nil)
end
end
it "should redirect_to new_user_path" do
controller.stub(:current_user, redirect: true).and_return(nil)
get :index
response.should be_redirect
end
end
end
The error I'm getting right now is
No route matches {:action=>"index", :controller=>"test"}
I would add the test#index route to config/routes.rb, but it doesn't recognize the Test Controller, so I want to do something like
MyApp::Application.routes.append do
controller :test do
get 'test/index' => :index
end
end
but I'm not sure where to add this or if this even works in rspec. Any help would be great!
If you are trying to test your ApplicationController, see this RSpec documentation about it. You will need to define methods like index inside the test, but it works well.

Rspec / Capybara: Testing if a controller method is called

Given I set up a HomeController with an index action
class HomeController < ApplicationController
def index
#users = User.all
end
end
and routed to it via the root path,
root :to => "home#index"
why does this request spec fail
it 'should called the home#index action' do
HomeController.should_receive(:index)
visit root_path
end
with the following message
Failure/Error: HomeController.should_receive(:index)
(<HomeController (class)>).index(any args)
expected: 1 time
received: 0 times
? Is it because the index method is called as a instance method instead of a class method?
I'm not sure exactly what you want to test, and I think there's some confusion as to what methods can be used where, so I'll try and give examples of Routing specs, Request Specs, Controller specs, and Feature specs, and hopefully one of them will be appropriate for you.
Routing
If you want to make sure that your root path gets routed to the home#index action, a routing spec may be appropriate:
spec/routing/routing_spec.rb
describe "Routing" do
it "routes / to home#index" do
expect(get("/")).to route_to("home#index")
end
end
Request
If you want to make sure that the index template gets rendered on a request to your root path, a request spec may be appropriate:
spec/requests/home_requests_spec.rb
describe "Home requests" do
it 'successfully renders the index template on GET /' do
get "/"
expect(response).to be_successful
expect(response).to render_template(:index)
end
end
Controller
If you want to make sure that the index template gets rendered on a request to the index action of your HomeController, a controller spec may be appropriate (and quite similar to a request spec in this case, but focused exclusively on the controller):
spec/controllers/home_controller_spec.rb
describe HomeController do
describe "GET index" do
it "successfully renders the index template" do
expect(controller).to receive(:index) # this line probably of dubious value
get :index
expect(response).to be_successful
expect(response).to render_template(:index)
end
end
end
Feature
If you want to make sure the page rendered by home#index has some specific content, a feature spec may be appropriate (and also the only place you can use Capybara methods like visit, depending on your Rails/RSpec version):
spec/features/home_features_spec.rb
feature "Index page" do
scenario "viewing the index page" do
visit root_path
expect(page).to have_text("Welcome to my awesome index page!")
end
end
class MyController < ApplicationController
def index
my_method
end
def my_method
end
end
describe MyController do
it 'calls my method' do
expect(controller).to receive(:my_method)
get :index
end
end

Ruby on Rails RSpec Routing fail

Rails newb here.
Trying to RSpec test a 200 status code for an index route.
In my index_controller_spec.rb:
require 'spec_helper'
describe IndexController do
it "should return a 200 status code" do
get root_path
response.status.should be(200)
end
end
routes.rb:
Tat::Application.routes.draw do
root to: "index#page"
end
index_controller:
class IndexController < ApplicationController
def page
end
end
When I visit on my browser all is fine but RSpec command line gives an error:
IndexController should return a 200 status code
Failure/Error: get '/'
ActionController::RoutingError:
No route matches {:controller=>"index", :action=>"/"}
# ./spec/controllers/index_controller_spec.rb:6:in `block (2 levels) in <top (required)>
'
I don't understand?!
Thanks.
Welcome to the Rails world! Testing comes in many different flavors. It appears that you're confusing a controller test with a routing test.
You're seeing this error because root_path is returning /. The get :action within an RSpec controller test is meant to call that method on that controller.
If you notice your error message, it says :action => '/'
To test your controller, change your test to:
require 'spec_helper'
describe IndexController do
it "should return a 200 status code" do
get :page
response.status.should be(200)
end
end
If you're interested in a routing test, see https://www.relishapp.com/rspec/rspec-rails/docs/routing-specs An example would be:
{ :get => "/" }.
should route_to(
:controller => "index",
:action => "page"
)

Rails - Testing ApplicationController with rspec

I want to put the common controller actions, index, show, create etc. in the ApplicationController like this:
class ApplicationController < ActionController::Base
respond_to :json
def index
#implementation
end
def show
#implementation
end
def update
#implementation
end
end
The app will only return JSON.
I have written the following spec to test this with RSPEC's annonymous controller
describe ApplicationController do
controller do ; end
describe 'Get :index' do
it 'should respond to index' do
get :index
response.code.should eq "200"
end
end
end
The above spec gives the following error:
ActionView::MissingTemplate: Missing template anonymous/index,
application/index with {:locale=>[:en], :formats=>[:json],
:handlers=>[:erb, :builder]}. Searched in: *
"#"
Can anyone suggest a way to make this work with the anonymous controller?
try this may be it helpful
your controller like
def index
end
your rspec testing like
describe "GET index" do
it "should respond to index" do
get :index
response.code.should eq "200"
end
end
create index.html.erb in your application/ folder
then test it.
describe "GET index" do
it "returns correct JSON" do
# #groups.should have(2).items
get :index, :format => :json
response.should be_success
body = JSON.parse(response.body)
body.should include('group')
groups = body['group']
groups.should have(2).items
groups.all? {|group| group.key?('customers_count')}.should be_true
groups.any? {|group| group.key?('customer_ids')}.should be_false
end
end

Resources