Inside a controller spec I have the following code...
subject do
get 'index'
puts 'response is ' + response.body
JSON.parse(response.body)
end
This works fine, getting the index action for the specific api controller. However when I try a show request, I don't know how to pass in a variable, so when I run...
subject do
get 'show'
puts 'response is ' + response.body
JSON.parse(response.body)
end
I get the error...
←[31mFailure/Error:←[0m ←[31mget 'show'←[0m
←[31mActionController::RoutingError←[0m:
←[31mNo route matches {:controller=>"api/example/v1/clinics", :action=>"show"}←[0m
There is a show action for the api/example/v1/clinics, of course I didn't pass the parameter which it needs, unsure how to do that. How would I get a show action working?
I tried something like
get 'api/example/v1/clinics/2'
but that does not work either. I can't seem to locate the documentation for this rails method either. Any help is appreciated. Thanks.
For controller actions that require parameters (for example 'id' is required by the show action) you need to pass it as a parameter to the get request:
get :show, id: 1
Or if using older 1.8 hash syntax:
get :show, :id => 1
You can pass in an id to get :show by:
get 'show', id: 2
Related
Edit 2: OMG I AM SO STUPID. In my spec I have a let(:response) {MyModel.create()} so thats why its failing. Going to delete post
(edited for clarity)
In my routes file
root "search_email#index"
get "search_email/retrieve_last_user_survey" => "search_email#retrieve_last_user_survey"
Controller
class SearchEmailController < ApplicationController
def retrieve_last_user_survey
render :json => "")
end
end
Spec file
require "rails_helper"
RSpec.describe SearchEmailController, type: :controller do
describe 'GET #retrieve_last_user_survey' do
before do
get :retrieve_last_user_survey, :params => { :email => 'abc#abc.com'}
end
it "returns http success" do
expect(response).to have_http_status(:success)
end
end
end
When try to run my test, i get this
Failure/Error: expect(response).to have_http_status(:success)
expected a response object, but an instance of Relational::Response (custom model name) was received
I have no idea why I am not getting a response object, I know I am hitting the controller method cause I inserted puts and I can see it.
Also on a semi related note. If i create a button that hits this route. why does it redirect me to a show route. I thought it would just return some http request that i can see in the dev console. I know cause said I dont have a show route or a show template.
It's not meant to be facetious, but to get the test to pass, replace the render line in the controller with:
head :ok
Does the test pass? Probably. So now add some expectation on the content header, and then finally the content itself.
If you break it down into small pieces, you should find the problem. It's not obvious from what you've shared, we can't see into the controller method.
I'm still fairly new to the rspec way. I've read many posts on a redirect_to but cannot seem to get passed this error. I'm trying to simulate the passing of form variable/value in my rspec test, but getting a routing error. I'm converting tests to rspec tests on an app that is live and working.
In my employees_micros_controller.rb, I have an update method that expects params[:employees_micro][:id]. My question is How do I simulate this in my rspec test?
Controller:
def update
#em = nil
# check for id from form
if params[:employees_micro][:id]
#em = EmployeesMicro.find_by_id(params[:employees_micro][:id])
end
....
end
Rspec Test: note: ### error line ###
# update and redirect
describe 'POST #update' do
it "updates employee_micro and redirect to employee_details" do
# #emp_micros set in before(each) above
#emp_micros.home_job = 123
# update method looks for params[:employees_micro][:id]
post :update, :employees_micro => { :id => #emp_micros } ### error line ###
expect(response).to redirect_to("employee_details_employee_path")
end
end
Error:
Failure/Error: post :update, :employees_micro => { :id => #emp_micros }
ActionController::RoutingError:
No route matches {:employees_micro=>{:id=>"11960"}, :controller=>"employees_micros", :action=>"update"}
Is my >> post :update line syntax correct?
I do not understand the routing error. I'm only trying to simulate passing a form variable to the update method from my test. If I remove everything after the post/put line, I still get the same error, so it is definitely on that line.
I've also tried using "put" in place of "post" in the test. It nets me the same error.
Thanks for any tips or advice.
The update route expects the :id param to be at the top level, so use:
post :update, :id => #emp_micros, :employees_micro => { <other attributes to update> }
I am getting an error testing a controller route despite being able to successfully load it via the browser. Rails4 + rspec.
Any ideas?
#controller spec
describe PublicSitesController do
describe "GET index" do
it "returns success" do
get :index #line 7 in the spec file
response.status.should == 200
end
end
end
#routes
get ":site_name/:page_name", to: "public_sites#show"
get ":site_name", to: 'public_sites#index'
get "/", to: 'public_sites#root'
#controller
class PublicSitesController < ApplicationController
def root
end
def index
end
def show
end
end
#the error:
Failures:
1) PublicSitesController GET index returns success
Failure/Error: get :index
ActionController::UrlGenerationError:
No route matches {:action=>"index", :controller=>"public_sites"}
# ./spec/controllers/public_sites_controller_spec.rb:7:in `block (3 levels) in <top (required)>'
Here are the relevant routes via rake routes:
GET /:site_name/:page_name(.:format) public_sites#show
POST /:site_name/:page_name(.:format) public_sites#receive_form
GET /:site_name(.:format) public_sites#index
GET / public_sites#root
You are missing some parameter on the request, the router doesn't know what to do with ":site_name", try something like:
get :index, site_name: 'something'
edit:
when you call get/post/etc inside a test you call the action name with that method, not the url, that way the controller test is independant of the url that make that action work (you can change the url and the controller will still work)
your route tells rails that it need some parameter named "site_name" so you need to tell rails what's inside "site_name" with a parameter for the action
if you want you can have routing tests, there you can test that some url goes to some controller's action with some value on some parameter https://www.relishapp.com/rspec/rspec-rails/v/2-3/docs/routing-specs
when you open the site on a browser you are not calling the action, you are actually running your whole application, then the routing system calls the controller's action
edit 2:
if you want to test the show action you should call it with
get :show, site_name: 'some_site', page_name: 'some_page'
I am trying to mock out the session hash for a controller like so:
it "finds using the session[:company_id]" do
session.should_receive(:[]).with(:company_id).and_return 100
Company.should_receive(:find).with(100)
get 'show'
end
When I call get 'show' it states:
received :[] with unexpected arguments
expected: (:company_id)
got: ("flash")
The controller code looks like:
def show
company_id = session[:company_id]
#company = Company.find params[company_id]
end
I have also simply tried setting
it "finds using the session[:company_id]" do
session[:company_id]= 100
Company.should_receive(:find).with(100)
get 'show'
end
but then get an issue about:
expected: (100)
got: (nil)
Anyone have ideas why?
I just ran into this. I couldn't manage to get should_receive to not interfere with the flash stuff.
But this let me test the behavior I was looking for:
it "should redirect to intended_url if set" do
request.env['warden'] = double(:authenticate! => true)
session.stub(:[]).with("flash").and_return double(:sweep => true, :update => true, :[]= => [])
session.stub(:[]).with(:intended_url).and_return("/users")
post 'create'
response.should redirect_to("/users")
end
Hope that helps...
I could not figure out how to mock the session container itself, however in most cases simply passing session data with request should be enough. So the test would split into two cases:
it "returns 404 if company_id is not in session" do
get :show, {}, {}
response.status.should == 404 # or assert_raises depending on how you handle 404s
end
it "finds using the session[:company_id]" do
Company.should_receive(:find).with(100)
get :show, {}, {:company_id => 100}
end
PS: forgot to mention I'm using some customized helpers from this snippet.
try this:
session.expects(:[]).with(has_entries('company_id' => 100))
It's because you fetch flash session from your controller. So define it. Flash is save in session.
it "finds using the session[:company_id]" do
session.stub!(:[]).with(:flash)
session.should_receive(:[]).with(:company_id).and_return 100
Company.should_receive(:find).with(100)
get 'show'
end
I'm getting a failing test here that I'm having trouble understanding. I'm using Test::Unit with Shoulda enhancement. Action in users_controller.rb I'm trying to test...
def create
unless params[:user][:email] =~ / specific regex needed for this app /i
# ...
render :template => 'sessions/new'
end
end
Test...
context 'on CREATE to :user' do
context 'with invalid email' do
setup { post :create, { 'user[email]' => 'abc#abcd' } }
should_respond_with :success
end
# ...
end
Fails because "response to be a <:success>, but was <302>". How is it 302?
Change action to...
def create
render :template => 'sessions/new'
end
Test still fails.
#Ola: You're wrong: POST is connected to create. PUT is normally connected to update.
A :forbidden is quiet odd though. Here are some suggestions to find the problem (I've never used Shoulda, but I don't think it is a problem with Shoulda.
Make sure the route is defined in config/routes.rb and check with rake routes
Do you have any before_filters that could be responsible for that behaviour (login filter, acts_as_authenticated etc..)? Checkout log/test.log. A halt in the filter chain shows up there.
Print out the response body puts response.body to see what you get returned.
Hope this helps.
If you're using default REST-ful URLs, you probably should use PUT, not POST... Since PUT is connected to create, POST to that URL will give you an unauthorized and redirect.