ruby-on-rails – 如何使用rspec测试路由约束
我正在开发一个主要用作API的应用程序(除了一些小的视图,如会话/注册,这将是“标准”).我喜欢在
Railscast #350: Versioning an API完成的方法,所以跟着它.我的路线看起来像:
namespace :api,:defaults => {:format => 'json'} do scope :module => :v1,:constraints => ApiConstraints.new(:version => 1,:default => false) do resources :posts,:only => [:create,:show,:destroy,:index] end scope :module => :v2,:constraints => ApiConstraints.new(:version => 2,:default => true) do resources :posts,:index] end end 在每个路径中,我的约束是一个新的ApiConstraints对象,它位于我的./lib文件夹中.班级看起来像这样: class ApiConstraints def initialize(options) @version = options[:version] @default = options[:default] end def matches?(req) @default || req.headers['Accept'].include?("application/vnd.MYAPP.v#{@version}") end end 现在,手动测试时,一切都按预期工作.在我的API中,每个版本可能有5到10个控制器,并且不想测试API约束对每个控制器的作用,因为这是没有意义的.我正在寻找一个测试我的API约束的规范文件,但我不确定在哪里放置该规范. 我已经尝试添加spec / routing / api_spec.rb文件来测试,但是它不能正常工作,因为它抱怨有些东西没有提供,像这样: it "should route an unversioned request to the latest version" do expect(:get => "/api/posts",:format => "json").to route_to(:controller => "api/v1/posts") end 即使控制器正确匹配,上述错误也会引发错误.它失败并出现以下错误: The recognized options <{"format"=>"json","action"=>"index","controller"=>"api/v1/posts"}> did not match <{"controller"=>"api/v1/posts"}>,difference: <{"format"=>"json","action"=>"index"}>. 请注意,控制器已正确确定,但由于我不想在此测试中测试格式和操作,所以错误.我想要有3个“API规范”: >它应该将未版本化的请求路由到最新版本 有没有人有写这些路线的规格的经验?我不想为API中的每个控制器添加规范,因为它们不对此功能负责. 解决方法
Rspec的route_to匹配者代表到
ActionDispatch::Assertions::RoutingAssertions#assert_recognizes
route_to的参数作为expected_options哈希传递(经过一些预处理,允许它也可以理解诸如项目#index的简写样式参数). 您希望匹配route_to匹配器(即{:get =>“/ api / posts”,:format =>“json”})的哈希实际上并不是一个格式正确的参数.如果你看看the source,你可以看到我们得到通过匹配的路径 path,query = * verb_to_path_map.values.first.split(‘?’) #first是一个确定的标志,我们期望只有一个键值对的散列.所以:format => “json”组件实际上被抛弃,并没有做任何事情. ActionDispatch断言希望您将完整的路径动词与一套完整的控制器,动作和路径参数.所以rspec匹配器只是传递它委托给它的方法的限制. 听起来像rspec的内置route_to匹配器不会做你想要的.所以下一个建议是假定ActionDispatch会做它应该做的事情,而只是为ApiConstraints类编写规范. 为此,我首先建议不要使用默认的spec_helper. Corey Haines有一个关于how to make a faster spec helper that doesn’t spin up the whole rails app的好主意.这可能不是完美的你的例子,但我只是想我会指出,因为你只是在这里实例化基本的红宝石对象,并不真正需要任何rails魔术.您也可以尝试使用ActionDispatch :: Request&依赖关系,如果你不想像这样在这里存根请求对象. 看起来像这样 规格/ lib目录/ api_constraint.rb require 'active_record_spec_helper' require_relative '../../lib/api_constraint' describe ApiConstraint do describe "#matches?" do let(:req) { Object.new } context "default version" do before :each do req.stub(:headers).and_return {} @opts = { :version => nil,:default => true } end it "returns true regardless of version number" do ApiConstraint.new(@opts).should match req end end end end … aaand我会让你弄清楚如何设置上下文/写出你的其他测试的期望. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |