在请求规范中对验证进行验证

Jon*_*sen 83 integration-testing rspec stubbing ruby-on-rails-3

在编写请求规范时,如何设置会话和/或存根控制器方法?我正在尝试在我的集成测试中删除身份验证 - rspec/requests

这是一个测试的例子

require File.dirname(__FILE__) + '/../spec_helper'
require File.dirname(__FILE__) + '/authentication_helpers'


describe "Messages" do
  include AuthenticationHelpers

  describe "GET admin/messages" do
    before(:each) do
      @current_user = Factory :super_admin
      login(@current_user)
    end

    it "displays received messages" do
      sender = Factory :jonas
      direct_message = Message.new(:sender_id => sender.id, :subject => "Message system.", :content => "content", :receiver_ids => [@current_user.id])
      direct_message.save
      get admin_messages_path
      response.body.should include(direct_message.subject) 
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

帮助者:

module AuthenticationHelpers
  def login(user)
    session[:user_id] = user.id # session is nil
    #controller.stub!(:current_user).and_return(user) # controller is nil
  end
end
Run Code Online (Sandbox Code Playgroud)

以及处理身份验证的ApplicationController:

class ApplicationController < ActionController::Base
  protect_from_forgery

  helper_method :current_user
  helper_method :logged_in?

  protected

  def current_user  
    @current_user ||= User.find(session[:user_id]) if session[:user_id]  
  end

  def logged_in?
    !current_user.nil?
  end
end
Run Code Online (Sandbox Code Playgroud)

为什么无法访问这些资源?

1) Messages GET admin/messages displays received messages
     Failure/Error: login(@current_user)
     NoMethodError:
       undefined method `session' for nil:NilClass
     # ./spec/requests/authentication_helpers.rb:3:in `login'
     # ./spec/requests/message_spec.rb:15:in `block (3 levels) in <top (required)>'
Run Code Online (Sandbox Code Playgroud)

Dav*_*sky 100

请求规范是一个瘦的包装器ActionDispatch::IntegrationTest,它不像控制器规范(包装ActionController::TestCase)那样工作.即使有可用的会话方法,我也不认为它是受支持的(即它可能存在,因为包含在其他实用程序中的模块也包含该方法).

我建议您通过发布用于验证用户身份的操作来登录.如果您为所有用户工厂设置密码'password'(例如),那么您可以执行以下操作:

def login(user)
  post login_path, :login => user.login, :password => 'password'
end

  • 如果我认为这是矫枉过正,我不会推荐它:) (18认同)
  • 我必须在Capybara中使用`page.driver.post` (17认同)
  • 这也是可靠地完成它的最简单方法.`ActionDispatch :: IntegrationTest`旨在模拟通过浏览器进行交互的一个或多个用户,而无需使用真正的浏览器.在单个示例中可能存在多个用户(即会话)和多个控制器,并且会话/控制器对象是在上一个请求中使用的对象.您在请求之前无权访问它们. (4认同)

fea*_*ool 60

设计用户注意事项......

BTW,@ David Chelimsky的回答可能需要稍微调整一下,如果你正在使用Devise.我在集成/请求测试中做了什么(感谢这个StackOverflow帖子):

# file: spec/requests_helper.rb
def login(user)
  post_via_redirect user_session_path, 'user[email]' => user.email, 'user[password]' => user.password
end
Run Code Online (Sandbox Code Playgroud)

  • 当我在rspec模型规范中使用'login user1'时,我得到#lttp :: Core的未定义局部变量或方法'user_session_path': (2认同)