【问题标题】:Rspec/Rails 4, access current_user from Rspec.feature spec?Rspec/Rails 4,从 Rspec.feature 规范访问 current_user?
【发布时间】:2016-08-11 22:03:25
【问题描述】:

我可以从控制器规格访问 current_user 没问题。在 Rspec.feature 规范中,我无法使 current_user 可用。

我需要 current_user 的原因是,我正在测试发送邀请功能。我导航到发送邀请的页面,填写邀请 [to_user] 字段,然后单击“发送邀请”。我想确保页面上显示正确的 Flash 消息。但是,我在通过单击“发送邀请”触发的控制器操作中将 sender_id 设置为 current_user id - 这是我需要定义 current_user 的地方。

我为控制器测试设置了 support/controller_macros.rb,如下所示:

module ControllerMacros
  def login_user
    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:user]
      user = FactoryGirl.create(:user)
      sign_in user
    end
  end
end

支持/devise.rb

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

login_user 在 Rspec.feature 规范中不可用...这是有道理的,因为类型是“功能”而不是“控制器”。我假设这就是原因。

我认为我应该能够使用 Rspec.feature 规范调用 sign_in。但这不起作用...... sign_in 方法也不可用。这是我正在尝试使用的规范:

require "rails_helper"

RSpec.feature "Carpool Invitations", :type => :feature do
    let!(:carpool) { FactoryGirl.create(:carpool)}
    let!(:user) { FactoryGirl.create(:user)}


  scenario "User sends a new carpool invite" do
        sign_in user

    visit new_carpool_invite_path(carpool)
    fill_in "invite[to_user]", :with => "matthewalexander108@gmail.com"
    click_button "Send Invitation"
    expect(page).to have_text("Invitation was successfully sent!")
  end
end

有没有办法配置 Rspec.feature 规范,以便它可以查看和使用 support/controller_macros.rb 文件中定义的 login_user 方法?我看过:

Why i can not get current_user while writing test case with Rspec and Capybara

但我无法得到我需要的东西。

更新:

我的问题不同,因为我正在运行集成测试,最终我正在测试页面的内容。我正在运行的集成测试涉及发送邀请,发送邀请操作会创建一个邀请对象,在创建邀请的过程中,current_user.id 添加为正在创建的邀请对象的sender_id。成功创建邀请后,同一页面会重新加载并显示一条 Flash 消息。

我正在测试 Flash 消息。

为此,我需要在创建邀请的操作中定义 current_user。

【问题讨论】:

  • 为什么不创建自己的模块助手,例如 module FeatureHelper 就像 module ControllerMacros 专门用于功能测试。
  • 您引用的问题的已接受答案的第一部分是您正在寻找的答案。不要尝试在功能规范中检查current_user;检查页面以查看谁已登录。
  • @DaveSchweisguth,我正在寻找的是下面 rmhunters 答案的第二部分。

标签: ruby-on-rails rspec devise capybara


【解决方案1】:

TL;DR

不要在特性规范中使用控制器助手——在 BDD 中,您希望特性规范通过浏览器 DSL(如 Capybara)完成所有工作。在您的情况下,最好编写一个单独的辅助方法来使用 Capybara 登录(示例如下)。


说明

您希望您的功能规范是从用户的角度来看的。用户不关心控制器如何创建用户会话,您的功能规范也不应该关心。它应该保持在规范类型的域内。

在您的情况下,更好的解决方案是编写另一个帮助方法(特别是针对:feature 规范),通过 Capybara 方法让用户登录,以便您的整个功能测试从相同的流程/角度进行。这是我在所有应用程序中使用的通用辅助方法:

# spec/support/feature_helpers.rb
module FeatureHelpers
  def sign_in
    @user = FactoryGirl.create(:user)
    visit "/"
    click_link "Sign In"
    fill_in "user_email", with: @user.email
    fill_in "user_password", with: @user.password
    click_button "Sign in"
  end
end

RSpec.configure do |config|
  config.include FeatureHelpers, :type => :feature
end

然后,您的规范将如下所示:

require "rails_helper"

RSpec.feature "Carpool Invitations", :type => :feature do
  let!(:carpool) { FactoryGirl.create(:carpool)}
  # you could still create a user here if you wanted

  scenario "User sends a new carpool invite" do
    sign_in
    visit new_carpool_invite_path(carpool)
    fill_in "invite[to_user]", :with => "matthewalexander108@gmail.com"
    click_button "Send Invitation"
    expect(page).to have_text("Invitation was successfully sent!")
  end
end

【讨论】:

  • 谢谢!这正是我一直在寻找的。效果很好。
  • 不客气!希望您使用了“更好”的解决方案......我实际上正在编辑我的答案以删除肮脏的解决方案,因为它甚至不能保证工作。
  • 我确实使用了“更好的解决方案”
  • 快速而肮脏的解决方案有点奇怪;)我肯定会删除它
  • 是的,它很容易受到副作用的影响,我删除了它。
【解决方案2】:

你的 rails_helper.rb 有这个吗?

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

仅用于测试,将此配置添加到您的 rails_helper.rb

require 'devise'

RSpec.configure do |config|
  #...
  config.include Devise::TestHelpers, type: :controller
  #... 
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多