How to test route constraints with rspec

烈酒焚心 提交于 2019-12-04 22:58:10

Rspec's route_to matcher delegates to ActionDispatch::Assertions::RoutingAssertions#assert_recognizes

The the argument to route_to is passed in as the expected_options hash (after some pre-processing that allows it to also understand shorthand-style arguments like items#index).

The the hash that you're expecting to match the route_to matcher (i.e., {:get => "/api/posts", :format => "json"}) is not actually a well-formed argument to expect. If you look at the source, you can see that we get the path to match against via

path, query = *verb_to_path_map.values.first.split('?')

The #first is a sure sign that we're expecting a hash with just one key-value pair. So the :format => "json" component is actually just being discarded, and isn't doing anything.

The ActionDispatch assertion expects you to be matching a complete path + verb to a complete set of controller, action, & path parameters. So the rspec matcher is just passing along the limitations of the method it delegates to.

It sounds like rspec's built-in route_to matcher won't do what you want it to. So the next suggestion would be to assume ActionDispatch will do what it is supposed to do, and instead just write specs for your ApiConstraints class.

To do that, I'd first recommend not using the default spec_helper. Corey Haines has a nice gist about how to make a faster spec helper that doesn't spin up the whole rails app. It may not be perfect for your case as-is, but I just thought I'd point it out since you're just instantiating basic ruby objects here and don't really need any rails magic. You could also try requiring ActionDispatch::Request & dependencies if you don't want to stub out the request object like I do here.

That would look something like

spec/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 I'll let you figure out exactly how to set up the context/write the expectations for your other tests.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!