开发者

Testing Rail's route's :constraints lambda with RSpec 2

开发者 https://www.devze.com 2023-03-04 02:57 出处:网络
Question: How do you setup/mock a rspec routing test to look more like a production rack environment? Bonus points for being able call a controller\'s authentication function first (eg ApplicationCo

Question:

How do you setup/mock a rspec routing test to look more like a production rack environment?

Bonus points for being able call a controller's authentication function first (eg ApplicationController.authenticate_user to set the session[:current_user_id]

Details:

I am using route :constraints to have www.example.com/ route to two different controllers & views depending on if the user is logged in or not.

root :to => 'intentions#latest', :constraints => lambda {|r| r.env['rack.session'].has_key?(:current_user_id) }
root :to => 'welcome#index'

I wanted to make sure that this bit of fragile routing has a proper test around it. The cukes are testing it but I wanted to do a bit deeper of testing, specifically as I messed up the :current_user_id and the cukes did not catch that. For example I fat fingered :current_user_id in my ApplicationController's authenticate_user() method开发者_开发技巧. Would love to call that in the before(:each) and make sure I am setting the correct session key.

So I created a file called /spec/routing/auth_routing_spec.rb and tried to follow the guide at http://relishapp.com/rspec/rspec-rails/v/2-6-rc/dir/routing-specs. I created the following spec:

it "/ should send me to home page" do
  get('/').should route_to(:controller => :index)
end

When I run the spec I run into this error on the route that has the :constraint. I am assuming that env['rack.session'] does not exists. I tried to mock the request object out via Rails.application.call(Rack::MockRequest.env_for('/')) but that did not help out.

Failure/Error: get('/').should route_to(:controller => :index)
NoMethodError:
  undefined method `has_key?' for nil:NilClass


Boring app details

rake about yields

Ruby version              1.9.2 (x86_64-darwin10.6.0)
RubyGems version          1.6.2
Rack version              1.2
Rails version             3.0.7
Active Record version     3.0.7
Action Pack version       3.0.7
Active Resource version   3.0.7
Action Mailer version     3.0.7
Active Support version    3.0.7

grep rspec gemfile.info yields

remote: git://github.com/rspec/rspec-rails.git
  rspec-rails (2.6.0.rc6)
    rspec (= 2.6.0.rc6)
  rspec (2.6.0.rc6)
    rspec-core (= 2.6.0.rc6)
    rspec-expectations (= 2.6.0.rc6)
    rspec-mocks (= 2.6.0.rc6)
  rspec-core (2.6.0.rc6)
  rspec-expectations (2.6.0.rc6)
  rspec-mocks (2.6.0.rc6)
rspec-rails!


I do something like in my controller specs, maybe the same approach would work here?

describe "some controller" do
  it "does something" do
    request.stub(:env => {'rack.session' => {'current_user' => '42'})
    get :my_action
    response.should be_cool
  end
end

Upon reflection, a better approach for you is probably:

class CurrentUserConstraint
  def self.matches?(request)
    request.session[:current_user_id].present?
  end
end

and:

root :to => 'intentions#latest', :constraints => CurrentUserConstraint.new

and then you have your logic in a class that is easily testable.

0

精彩评论

暂无评论...
验证码 换一张
取 消