【问题标题】:RSpec Devise sign_in not setting current_user in controllerRSpec设计sign_in未在控制器中设置current_user
【发布时间】:2014-12-04 05:51:02
【问题描述】:

我已按照以下说明进行操作: Devise wiki 使用 RSpec 设置控制器测试,但我的测试失败了。

它似乎重定向到http://test.host而不是呈现页面

以下是回复中的一些内容:

@current_user=nil
@_response_body=["<html><body>You are being <a href=\"http://test.host/\">redirected</a>.</body></html>"]

我的测试控制器规格如下:

require 'rails_helper' require 'devise'

RSpec.describe Services::MyController, :type => :controller do   
  include Devise::TestHelpers   
  include Warden::Test::Helpers   

  describe "administrator" do
    before :each do
      @request.env["devise.mapping"] = Devise.mappings[:user]
      #administrator wraps user and adds role
      @admin = FactoryGirl.create(:administrator)
      @admin.confirm!
      sign_in @admin
    end
    describe "GET index" do
      it "returns http success" do
        #puts current_user.to_yaml
        get :index
        expect(response).to be_success
      end
    end   
  end 
end

看起来它自动重定向到 test.host(不知道它来自哪里),因为没有定义当前用户?

在我的应用程序控制器中,如果用户在其他地方登录,我有代码设置以注销用户。这似乎是用户被自动重定向的地方。通过在此处转储 current_user,我可以看到 'current_sign_in_ip' 为 nil,因为未设置所有其他登录属性。

应用控制器

def check_request_ip
    puts current_user.to_yaml
    puts request.remote_ip
    unless current_user.nil? || request.remote_ip == current_user.current_sign_in_ip
      Rails.logger.warn "User already logged in from #{current_user.current_sign_in_ip} and trying to log in from #{request.remote_ip}."
      sign_out_and_redirect(current_user)
    end
  end

rails_helper.rb

ENV["RAILS_ENV"] ||= 'test'
require 'spec_helper'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'

Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }

ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)

RSpec.configure do |config|

  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  config.use_transactional_fixtures = true

  config.infer_spec_type_from_file_location!
end

spec_helper.rb

require 'factory_girl'
require 'devise'
RSpec.configure do |config|
  begin
    config.include Warden::Test::Helpers
    config.include Devise::TestHelpers, :type => :controller
    config.include FactoryGirl::Syntax::Methods

    config.filter_run :focus
    config.run_all_when_everything_filtered = true

    if config.files_to_run.one?
      config.default_formatter = 'doc'
    end
    config.profile_examples = 10

    config.order = :random

    Kernel.srand config.seed

    config.expect_with :rspec do |expectations|
      expectations.syntax = [:expect, :should]
    end

    config.mock_with :rspec do |mocks|
      mocks.syntax = :expect
      mocks.verify_partial_doubles = true
    end
  end
end

test.rb

Go2Asset::Application.configure do

  config.stretches = Rails.env.test? ? 1 : 10
  config.cache_classes = true

  config.eager_load = false

  config.serve_static_assets = true
  config.static_cache_control = "public, max-age=3600"

  config.consider_all_requests_local = true
  config.action_controller.perform_caching = false

  config.action_dispatch.show_exceptions = false

  config.action_controller.allow_forgery_protection = false

  config.action_mailer.delivery_method = :test
  config.action_mailer.default_url_options = { :host => 'localhost:3000' }

  config.active_support.deprecation = :stderr
end

【问题讨论】:

  • 您的班级名称是管理员还是用户?因为如果它是管理员而不是用户,你需要在你的控制器上放一个before_filter authenticate_administrator! 而不是authenticate_user!
  • 没有。管理员只是为用户添加管理员角色的工厂助手。

标签: ruby-on-rails unit-testing ruby-on-rails-4 rspec devise


【解决方案1】:

因为您不需要描述两个描述,因为它们彼此独立(它们是两个不同的场景),这就是为什么 current_user 在第二个描述中为 nil

尝试定义一个用于创建用户并让他登录的方法,您可以通过在 support/devise.rb 中创建一个方法来实现,如下所示:

module ControllerMacros
  def login_user
    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:user]
      user = FactoryGirl.create(:user) # in factories.rb you should create a factory for user
      user.confirm! # or set a confirmed_at inside the factory. Only necessary if you are using the "confirmable" module
      sign_in user
    end
  end
end

RSpec.configure do |config|
  config.include Devise::TestHelpers, :type => :controller
  config.extend ControllerMacros, :type => :controller
end

然后删除第一个describe,在第二个describe之前只写get:index

login_user

另一种解决方案是先将描述嵌套到 login_user,如下所示:

describe "something" do
  login_user
  describe "something 1" do
    #yourcode
  end

end

【讨论】:

  • 我的描述是嵌套的。我希望代码在每个嵌套描述之前运行以设置环境。无论如何,我尝试将代码移动到描述中,但它仍然不起作用。
  • 即使在单个测试用例中移动代码也会导致同样的问题。即使我在登录后尝试放置当前用户,我也一无所获。
  • 我想我可能知道原因,你能粘贴你的 rails_helper.rb 和 env.rb 吗?
  • 我添加了 spec_helper rails_helper 和 test.rb
猜你喜欢
  • 1970-01-01
  • 2015-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多