How to specify controller name in test::unit - ruby-on-rails

I have my brands controller in app/controllers/merchant/brands_controller.rb
I'm trying to write a functional test for it. I've defined test class as
require 'test_helper'
class Merchant::BrandsControllerTest < ActionController::TestCase
include Devise::TestHelpers
setup do
#user = users(:one)
sign_in #user
#brand= brands(:one)
end
test "should get index" do
get :index
assert_response :success
end
end
but the tests throw an error saying
ActionController::RoutingError: No route matches {:controller=>"merchant/brands", :action=>"new"}
Why is it using 'merchant/brands' as controller name?
Or can I specify custom route to make a request to 'new' method?
My routes look like this
namespace :merchant do
resources :accounts do
resources :brands
end
end
I

It seems you forgot the accounts part of your route.
Try with
class Merchant::Accounts::BrandsControllerTest

Related

Rspec no route matches polymorphic

I am trying to test my polymorphic comments create action but I always get no route matches error in rspec.
class CommentsController < ApplicationController
before_action :authenticate_user!
def create
#comment = #commentable.comments.new(comment_params)
#comment.user_id = current_user.id
#comment.save
redirect_to :back, notice: "Your comment was successfully posted."
end
private
def comment_params
params.require(:comment).permit(:body)
end
end
Rspec
describe "POST #create" do
context "with valid attributes" do
before do
#project = FactoryGirl.create(:project)
#comment_attr = FactoryGirl.build(:comment).attributes
end
it "creates a new comment" do
expect{
post :create, params: { project_id: #project, comment: #comment_attr }
}.to change(Comment, :count).by(1)
end
end
end
I am using this approach for testing create action in my another controllers and there is everything good, but here from some reason is throws error. I think my error is in line where I pass params to post create action but I do not see error.
UPDATE
resources :projects do
resources :comments, module: :projects
resources :tasks do
resources :comments, module: :tasks
end
end
UPDATE 2
Failure/Error: post :create, params: { project_id: #project,
commentable: #project, comment: #comment_attr }
ActionController::UrlGenerationError:
No route matches {:action=>"create", :comment=>{"id"=>nil, "commentable_type"=>nil, "commentable_id"=>nil, "user_id"=>nil,
"body"=>"MyText", "created_at"=>nil, "updated_at"=>nil,
"attachment"=>nil}, :commentable=>#, :controller=>"comments", :project_id=>#}
I think that your controller namespace does not match the routes you define. The controller is defined to not be nested (CommentsController) whereas the corresponding routes are nested and inside a module projects as well. Nesting the routes will have no influence on the controller ActionDispatch is looking for. But defining a module for the route will lead to rails expecting a controller inside the module namespace. In your case that would be Projects::CommentsController and Tasks::CommentsController. Please see "2.6 Controller Namespaces and Routing" of "Rails Routing from the Outside In" for further details.
I added your routes to a brand new rails project and ran rails routes. The output is:
Prefix Verb URI Pattern Controller#Action
project_comments GET /projects/:project_id/comments(.:format) projects/comments#index
POST /projects/:project_id/comments(.:format) projects/comments#create
...
You can therefor either remove the module definition from your routes
resources :projects do
resources :comments
resources :tasks do
resources :comments
end
end
or nest the controllers inside in a project/task namespace. Given that you want polymorphism for your comments, I would advise using the first option.

ActionController::UrlGenerationError: No route matches when trying to test the controller

I'm getting an ActionController::UrlGenerationError: No route matches (:action => "edit", :controller => "goals") error, when I'm trying to test the goals controller
Here is my goals_controller_test.rb
require 'test_helper'
class GoalsControllerTest < ActionController::TestCase
test "should be redirected when not logged in" do
get :new
assert_response :redirect
assert_redirected_to new_user_session_path
end
test "should render the new page when logged in" do
sign_in users(:guillermo)
get :new
assert_response :success
end
test "should get edit" do
get :edit
assert_response :success
end
test "should get show" do
get :show
assert_response :success
end
end
This is my routes.rb
Rails.application.routes.draw do
devise_for :users
authenticated :user do
root 'du#dashboard', as: "authenticated_root"
end
resources :goals
root 'du#Home'
end
My goals_controller.rb
class GoalsController < ApplicationController
before_filter :authenticate_user!, only: [:new]
def new
end
def edit
end
def show
end
private
def find_user
#user = User.find(params[:user_id])
end
def find_goal
#goal = Goal.find(params[:id])
end
end
I find it weird that if I use get 'goals/edit' instead of resources :goals the test passes.
Thank you very much for any guideline.
When you use resources :goals Rails generates for you the following routes (RESTful):
goals GET /goals(.:format) goals#index
POST /goals(.:format) goals#create
new_goal GET /goals/new(.:format) goals#new
edit_goal GET /goals/:id/edit(.:format) goals#edit
goal GET /goals/:id(.:format) goals#show
PATCH /goals/:id(.:format) goals#update
PUT /goals/:id(.:format) goals#update
DELETE /goals/:id(.:format) goals#destroy
As you can see, to hit the edit action /goals/:id/edit you need to pass an :id. That way, in your controller you'll be able to find the record by the given :id => Goal.find(params[:id]). So, in your tests you need to pass this :id, something like:
get :edit, id: 1 # mapping to /goals/1/edit
If you manually add this route get 'goals/edit', it works because it maps directly to /goals/edit (NOTE there is no :id).
Btw, I recommend you to review the official Routing guides: http://guides.rubyonrails.org/routing.html
#goal = Goal.create(your params here) or use factory girl gem or fixtures
you should pass id get :edit ,id: #goal
useful article

Rails 4: testing GET request on a namespaced controller

I have a failing test that I'm struggling to understand. I have a controller class Users::QueriesController < ApplicationController at app/controllers/users/queries_controller.rb which has a show action, and a corresponding namespaced route:
namespace :users do
resources :queries
end
I also have a test at test/controllers/users/queries_controller_test.rb:
require 'test_helper'
class Users::QueriesControllerTest < ActionController::TestCase
test "accessing :show action" do
get :show
assert_response :success
end
end
Running this test results in ActionController::UrlGenerationError: No route matches {:controller=>"users/queries", :action=>"show"}.
Running rake routes includes this line: users_query GET /users/queries/:id(.:format) users/queries#show.
What's going wrong here? I'm using Rails 4.0.0.
I think you need to provide an id to the show action
test "accessing :show action" do
get :show, {:id => 1}
assert_response :success
end
That's the right way prior to rails 4.
Please have a try, and let me know the outcome.

Rails engine: rake routes show its routes but on rspec execution "No route matches" is thrown

I'm trying to test a controller that is inside an engine my application is using. The spec is not within the engine, but in the application itself (I tried to test within the engine but also had problems).
My engine has the following routes.rb:
Revision::Engine.routes.draw do
resources :steps, only: [] do
collection { get :first }
end
end
The engine is mounted on the application routes.rb normally:
mount Revision::Engine => "revision"
When I run rake routes, at the last lines I get:
Routes for Revision::Engine:
first_steps GET /steps/first(.:format) revision/steps#first
root / revision/steps#first
On my engine's controller (lib/revision/app/controllers/revision/steps_controller.rb), I have:
module Revision
class StepsController < ApplicationController
def first
end
end
end
On Rspec, I test this controller with:
require 'spec_helper'
describe Revision::StepsController do
it "should work" do
get :first
response.should be_success
end
end
Then when I run this spec, I get:
ActionController::RoutingError:
No route matches {:controller=>"revision/steps", :action=>"first"}
To be sure that the route doesn't really exist, I added this to the spec:
before do
puts #routes.set.to_a.map(&:defaults)
end
And the result is this:
[...]
{:action=>"show", :controller=>"devise/unlocks"}
{:action=>"revision"}
It has only the :action parameter.
What may be wrong?
When you're trying to test an engine's controllers, you need to specify what route set you want the controller test to use, otherwise it will run it against the main app's. To do that, pass use_route: :engine_name to the get method.
require 'spec_helper'
describe Revision::StepsController do
it "should work" do
get :first, use_route: :revision # <- this is how you do it
response.should be_success
end
end

RoutingError in Rspec

I keep running across this error for a GET request to show action.
1) ShopController GET 'show' should be successful
Failure/Error: get 'show', :id=>#shop.user.nickname
ActionController::RoutingError:
No route matches {:id=>"picardo", :controller=>"shop", :action=>"show"}
# ./spec/controllers/shop_controller_spec.rb:8:in `block (3 levels) in <top (required)>'
My routes look like this.
#routes.rb
resources :shop, :only=>[:show]
This is the controller spec:
#shop_controller_spec.rb
before(:each) do
#shop = Fabricate(:shop)
end
describe "GET 'show'" do
it "should be successful" do
get 'show', :id=>#shop.user.nickname
response.should be_success
end
end
And teh controller:
def show
#user = User.find(:first,:conditions=>{:nickname=>params[:id]})
#shop = #user.shop
end
You have to follow some rails rules.
If you have a singular resource you have to write resource :shop and if you have the plural resources you have to write resources :shops. You can run rake routes command to see the difference.
You wrote resources :shop and request sends to ShopController that is not exist in your application because I am sure that controller named ShopsController. Because the another rails rule is to name controllers in plural form and models in singular.
Or just write a controller name in routes: resources :shop, :controller => 'shops'

Resources