Mar*_*her 45 rspec routes ruby-on-rails-3 ruby-on-rails-3.1
我编写了一个带有命名空间Posts的Rails 3.1引擎.因此,我的控制器可以在app/controllers/posts /中找到,我的模型可以在app/models/posts等中找到.我可以很好地测试模型.一个型号的规格看起来像......
module Posts
  describe Post do
    describe 'Associations' do
      it ...
      end
......一切正常
但是,控制器的规格不起作用.Rails引擎安装在/ posts,但控制器是Posts :: PostController.因此,测试将控制器路由视为帖子/帖子.
  describe "GET index" do
    it "assigns all posts as @posts" do
      Posts::Post.stub(:all) { [mock_post] }
       get :index
       assigns(:posts).should eq([mock_post])
    end
  end
产量......
  1) Posts::PostsController GET index assigns all posts as @posts
     Failure/Error: get :index
     ActionController::RoutingError:
     No route matches {:controller=>"posts/posts"}
     # ./spec/controllers/posts/posts_controller_spec.rb:16
我已经在测试应用程序的路由文件...:命名空间等尝试了各种技巧,但无济于事.
我该如何工作?似乎它不会,因为引擎将控制器置于/ post,但命名空间将控制器置于/ posts/posts以进行测试.
Ben*_*ret 42
我假设您正在使用虚拟轨道应用程序测试您的引擎,就像enginex生成的应用程序一样.
您的引擎应该安装在虚拟应用程序中:
在spec/dummy/config/routes.rb:
Dummy::Application.routes.draw do
  mount Posts::Engine => '/posts-prefix'
end
我的第二个假设是你的发动机是孤立的:
在lib/posts.rb:
module Posts
  class Engine < Rails::Engine
    isolate_namespace Posts
  end
end
我不知道这两个假设是否真的需要,但这就是我自己的引擎的结构.
解决方法很简单,而不是这个
get :show, :id => 1
用这个
get :show, {:id => 1, :use_route => :posts}
该:posts符号应该是你的引擎的名称,而不是在那里安装的路径.
这是有效的,因为get方法参数直接传递给ActionDispatch::Routing::RouteSet::Generator#initialize(在此定义),而这又用于@named_route从中获取正确的路径Rack::Mount::RouteSet#generate(参见此处和此处).
插入导轨内部很有趣,但非常耗时,我不会每天都这样做;-).
HTH
Rya*_*igg 22
我工作围绕这一问题通过重写get,post,put,和delete提供的方法,使得它,以便他们总是通过use_route作为参数.
我用Benoit的答案作为基础.谢谢哥们儿!
module ControllerHacks
  def get(action, parameters = nil, session = nil, flash = nil)
    process_action(action, parameters, session, flash, "GET")
  end
  # Executes a request simulating POST HTTP method and set/volley the response
  def post(action, parameters = nil, session = nil, flash = nil)
    process_action(action, parameters, session, flash, "POST")
  end
  # Executes a request simulating PUT HTTP method and set/volley the response
  def put(action, parameters = nil, session = nil, flash = nil)
    process_action(action, parameters, session, flash, "PUT")
  end
  # Executes a request simulating DELETE HTTP method and set/volley the response
  def delete(action, parameters = nil, session = nil, flash = nil)
    process_action(action, parameters, session, flash, "DELETE")
  end
  private
  def process_action(action, parameters = nil, session = nil, flash = nil, method = "GET")
    parameters ||= {}
    process(action, parameters.merge!(:use_route => :my_engine), session, flash, method)
  end
end
RSpec.configure do |c|
  c.include ControllerHacks, :type => :controller
end
Mar*_*ars 19
使用rspec-rails routes指令:
describe MyEngine::WidgetsController do
  routes { MyEngine::Engine.routes }
  # Specs can use the engine's routes & named URL helpers
  # without any other special code.
end
根据这个答案,我选择了以下解决方案:
#spec/spec_helper.rb
RSpec.configure do |config|
 # other code
 config.before(:each) { @routes = UserManager::Engine.routes }
end
该额外的好处是,你不需要有before(:each)在每个控制器规格块.
| 归档时间: | 
 | 
| 查看次数: | 9499 次 | 
| 最近记录: |