rails rspec与devise gem共享示例

时间:2013-07-02 16:29:26

标签: ruby-on-rails rspec devise

我有这些用于测试控制器身份验证的shared_examples_for方法。

支持/控制器/ authentication_helpers.rb

module ControllerHelpers
  include Devise::TestHelpers

  shared_examples_for 'authenticate user' do |user, method, action, url_params={}|
    before(:each) do 
      setup_controller_for_warden
      request.env["devise.mapping"] = Devise.mappings[:user]
    end
    it "should redirect visitors to login page" do
      sign_out user
      if method == :get
        get action, url_params
      elsif method == :post
        post action, url_params
      elsif method == :put
        put action, url_params
      elsif method == :delete
        delete action, url_params
      end
      response.should redirect_to new_user_session_path
    end
    it "should allow user" do
      sign_in user
      if method == :get
        get action, url_params
      elsif method == :post
        post action, url_params
      elsif method == :put
        put action, url_params
      elsif method == :delete
        delete action, url_params
      end
      response.should be_success
    end
  end

end

我想将它与我的控制器规范文件一起使用。

brief_controller_spec.rb

require 'spec_helper'

describe BriefController do
  render_views

  before(:all) do
    @customer=Factory(:customer)
    @project=Factory(:project_started, :owner => @customer)
  end

  context 'get :new' do
    it_behaves_like 'authenticate user', @customer, :get, :new, {:project_id => @project.to_param} 
  end
end

当我运行这些spec文件时,遇到错误

Failure/Error: sign_in user
     RuntimeError:
       Could not find a valid mapping for

你知道我该怎么处理这个错误吗?

3 个答案:

答案 0 :(得分:0)

我在这里错了,但我认为:

@customer=Factory(:customer)
@project=Factory(:project_started, :owner => @customer)

应该是:

@customer=FactoryGirl(:customer)
@project=FactoryGirl(:project_started, :owner => @customer)

简单的错误,我自己做过几次。尝试一下,看看它是否解决了问题,希望它有所帮助。

答案 1 :(得分:0)

我认为问题是it_behaves_like的参数在执行before代码之前得到评估,因此第一个参数(@user)的计算结果为nil,导致进一步的问题我浪费了很多时间用我自己的代码追逐这个问题。

在相关的一点上,我最近阅读了一个建议,以避免在这些类型的测试中使用实例变量,因为当它们未定义时,您希望它们的引用失败。这对我来说很有意义,这就是我现在所做的。

答案 2 :(得分:0)

我使用let block for instance variables解决了我的问题。

shared_examples_for 'authenticate user' do |method, action|
    before(:each) do 
      setup_controller_for_warden
      request.env["devise.mapping"] = Devise.mappings[:user]
    end
    it "should redirect visitors to login page" do
      if method == :get
        get action, url_params
      elsif method == :post
        post action, url_params
      elsif method == :put
        put action, url_params
      elsif method == :delete
        delete action, url_params
      end
      response.should redirect_to new_user_session_path
    end

<强> controller_spec.rb

context 'get :new' do
    it_behaves_like 'authenticate user', :get, :new do 
      let(:user) { @customer }
      let(:url_params) { { :project_id => @project.to_param } }
    end
  end