根据我对rspec spec的理解,我希望通过以下示例。
describe ApplicationController do
controller do
def test
end
end
it "calls actions" do
get :test
end
end
相反,它失败了:
No route matches {:controller=>"anonymous", :action=>"test"}
我甚至尝试在路径文件中为“匿名”控制器定义路由,但无济于事。这里有什么我想念的吗?这应该有用,不应该吗?
答案 0 :(得分:24)
要在匿名控制器规范中使用自定义路由,您需要修改前一个块中的路由集。 RSpec已在前一个块中使用resources :anonymous
设置RESTful路由,并在后块中恢复原始路由。因此,要获得自己的路线,只需在@routes
上调用draw并添加所需内容。
以下是测试ApplicationController
rescue_from CanCan::AccessDenied
规范的示例
require 'spec_helper'
describe ApplicationController
controller do
def access_denied
raise CanCan::AccessDenied
end
end
before do
@routes.draw do
get '/anonymous/access_denied'
end
end
it 'redirects to the root when access is denied' do
get :access_denied
response.should redirect_to root_path
end
it 'sets a flash alert when access is denied' do
get :access_denied
flash.alert.should =~ /not authorized/i
end
end
<强>更新强>
在RSpec 2.12附近,对此的处理得到了改善。如果您使用&gt; 2.12然后你不再需要挂钩@routes
。
答案 1 :(得分:21)
我遇到了类似的问题。在我的例子中,解决方案是在测试中的get请求中包含:id参数。
即
get :test, :id => 1
检查您的路线并查看您是否缺少某个参数(可能是:id),然后将其添加到测试中。
答案 2 :(得分:3)
我遇到了同样的问题,我读了这个controller
方法代码(定义为here):
def controller(base_class = nil, &body)
base_class ||= RSpec.configuration.infer_base_class_for_anonymous_controllers? ?
controller_class :
ApplicationController
metadata[:example_group][:described_class] = Class.new(base_class) do
def self.name; "AnonymousController"; end
end
metadata[:example_group][:described_class].class_eval(&body)
# ADD ROUTES IN BEFORE BLOCK
before do
@orig_routes, @routes = @routes, ActionDispatch::Routing::RouteSet.new
@routes.draw { resources :anonymous } # <==== HERE ARE THE ROUTES
end
after do
@routes, @orig_routes = @orig_routes, nil
end
end
代码中的大写注释是我的,基本上你只能在使用这个方法时使用标准的restful路由。此外,您不能在routes.rb
文件中使用自定义路由,因为它们会被覆盖整个示例并在之后恢复。
答案 3 :(得分:3)
似乎rspec为您提供了一组RESTful路由。因此,如果您只在匿名控制器中使用标准操作名称,则不会出现此问题。到目前为止,我从来没有理由使用除“索引”之外的任何东西。
describe ApplicationController do
describe 'respond_with_foo' do
controller do
def index
respond_with_foo
end
end
it 'should respond with foo' do
get :index
response.should be_foo
end
end
end
答案 4 :(得分:1)
我遇到了同样的问题,并找到了一个适合我的解决方案。关键是在测试规范中映射出那些路线:
require 'spec_helper'
describe ApplicationController do
#Base class should be inferred
controller do
def not_found
raise ActiveRecord::RecordNotFound
end
end
def with_error_routing
with_routing do |map|
map.draw do
get '/not_found' => "anonymous#not_found", :as => :not_found
end
yield
end
end
describe "handling ActiveRecord::RecordNotFound" do
it "renders the 404 template" do
with_error_routing do
get :not_found
response.should render_template 'error/404'
end
end
end
end
答案 5 :(得分:0)
我能够通过以下补丁来解决这个问题:
module RSpec::Rails
module ControllerExampleGroup
module ClassMethods
def controller(base_class = nil, &body)
base_class ||= RSpec.configuration.infer_base_class_for_anonymous_controllers? ?
controller_class :
ApplicationController
metadata[:example_group][:described_class] = Class.new(base_class) do
def self.name; "AnonymousController"; end
end
metadata[:example_group][:described_class].class_eval(&body)
######## PATCH START ########
custom_routes = @custom_routes # Copy over routes to local variable so it will be accessible
before do
@orig_routes, @routes = @routes, ActionDispatch::Routing::RouteSet.new
if custom_routes # if this was set then pass that to the draw function
@routes.draw &custom_routes
else
@routes.draw { resources :anonymous } # else do what it used to do before
end
######### PATCH END #########
routes = @routes
described_class.send(:define_method, :_routes) { routes }
end
after do
@routes, @orig_routes = @orig_routes, nil
end
end
######## PATCH START ########
def custom_routes &block
@custom_routes = block
end
######### PATCH END #########
end
end
端
在spec_helper中需要该文件,然后在测试中只需执行:
describe ApplicationController do
describe 'respond_with_foo' do
custom_routes do
get :bar, controller: :anonymous, action: :bar
end
controller do
def index
respond_with_foo
end
end
it 'should respond with foo' do
get :index
response.should be_foo
end
end
end
如果有人问,我在infer_base_class_for_anonymous_controllers设置为false的情况下测试了这段代码。