存根设计身份验证时的控制器规范永远不会调用控制器操作

时间:2016-02-24 18:29:28

标签: ruby-on-rails ruby rspec devise

因此,当我尝试为我正在处理的rails应用程序编写一些控制器规范时,我遇到了一个非常奇怪的问题。基本上在高级别,似乎规范实际上从未实际调用控制器动作。我做过的一些事情发现了......

  1. 在做了一些环顾之后,我试图查看它是否可能是路由问题,为了测试这个,我使用了controller.index,并且确实调用了操​​作并且测试通过了。话虽如此,当我试图调用需要参数的动作时,这显然会导致问题,所以我想让#get|#post等工作。

  2. 当我在控制器操作中运行expect(response).to be_successful并编写fail 'some message'时,测试仍然通过,这进一步证明控制器操作周围没有任何事情发生。

  3. 我开始通过从application_controller中删除before_filter :authenticate_user!来阻止设计验证用户,然后无论出于何种原因规范运行并正确执行操作并且规范通过。现在,即使在使用#get时,这种情况也会发生,这与路由问题的理论相反。

  4. 由于最后一点,我认为问题在于如何处理设计auth,以便触及这个堆栈中唯一没有直接开箱即用的东西是控制器帮助器我在点击受保护的视图之前使用的身份验证,这是直接从设备上的设备wiki中提取的。可以在这里看到:

    def sign_in(user = double('user'))
      if user.nil?
        allow(request.env['warden']).to receive(:authenticate!).and_throw(:warden, {:scope => :user})
        allow(controller).to receive(:current_user).and_return(nil)
      else
        allow(request.env['warden']).to receive(:authenticate!).and_return(user)
        allow(controller).to receive(:current_user).and_return(user)
      end
    end
    

    现在即使我认为问题在于设计,但提供其他所有内容的示例可能是个好主意。所以,让我给你一块土地(当然有些东西被擦掉并简化了):

    routes.rb中:

    namespace :api, path: '', constraints: { subdomain: 'api' }, defaults: { format: :json } do
      namespace :v1 do
        ..
        resources :accounts
      end
    end
    

    alerts_controller.rb:

    class AlertsController < ApplicationController
      respond_to :html
    
      def index
        @alerts = Alert.all
      end
    
    end
    

    alerts_controller_spec.rb:

    require 'rails_helper'
    
    RSpec.describe AlertsController, type: :controller do
      let(:user){ create :user, :admin }
      let(:alert){ create :alert }
    
      before do
        sign_in user
      end
    
      describe 'GET index' do
        it 'responds successfully' do
          get :index
          expect(assigns(:alerts)).to eq [alert]
        end
       end
    end
    

    rake routes => GET /v1/alerts(.:format) api/v1/alerts#index {:subdomain=>"api"}

    任何帮助都会受到高度赞赏,因为我很难过。

2 个答案:

答案 0 :(得分:0)

不要为此写自己的帮手。 Devise只为此提供帮助

将其包含在您的规格中

data Mon m a b where
  Mon :: m -> Mon m a a

然后使用它。在你的情况下,你需要做的就是改变这个

#spec/rails_helper.rb
...
RSpec.configure do |config|
  config.include Devise::TestHelpers, type: :controller
end

到这个

before do
  sign_in user
end

答案 1 :(得分:0)

我想出了这个问题,说实话,这是非常愚蠢和我自己的错:P。在我的应用程序控制器中,有一个use_user_timezone个过滤器。如果有current_user,则只会将around过滤器添加到回调中。早些时候,出于某种原因,我阻止了周围过滤器中的代码运行,除非Rails.env.test? == true。显然我没有任何理由编写这段代码。问题是我没有阻止 around_filter 运行,如果它是测试环境,但是我正在阻止如果是测试环境,则运行过滤器方法中的代码。因此我没有让任何代码执行for around过滤器,这当然导致控制器操作的问题永远不会执行。

设计似乎在混合中出现问题的原因是因为围绕过滤器执行依赖于current_user存在。由于没有current_user,因此没有发生身份验证时,控制器流程仍在继续,没有问题。

将它包装起来......像往常一样,在将这样的更改添加到代码库时要特别注意,因为这样的小错误会导致后来出现严重的问题:)。