Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 3 请求规范中的存根身份验证_Ruby On Rails 3_Rspec_Integration Testing_Stubbing - Fatal编程技术网

Ruby on rails 3 请求规范中的存根身份验证

Ruby on rails 3 请求规范中的存根身份验证,ruby-on-rails-3,rspec,integration-testing,stubbing,Ruby On Rails 3,Rspec,Integration Testing,Stubbing,编写请求规范时,如何设置会话和/或存根控制器方法? 我试图在我的集成测试(rspec/requests)中取消身份验证 下面是一个测试示例 require File.dirname(__FILE__) + '/../spec_helper' require File.dirname(__FILE__) + '/authentication_helpers' describe "Messages" do include AuthenticationHelpers describe "

编写请求规范时,如何设置会话和/或存根控制器方法? 我试图在我的集成测试(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
助手:

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
以及处理身份验证的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
class ApplicationController
为什么不可能访问这些资源

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)>'
1)消息获取管理/消息显示收到的消息
失败/错误:登录(@current_user)
命名错误:
nil:NilClass的未定义方法“session”
#./spec/requests/authentication\u helpers.rb:3:in'login'
#./spec/requests/message_spec.rb:15:in'block(3层)in'

请求规范是一个很薄的包装,与控制器规范(包装)不同。即使有可用的会话方法,我也不认为它是受支持的(也就是说,它可能存在,因为包含在其他实用程序中的模块也包含该方法)

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

def login(user) post login_path, :login => user.login, :password => 'password' end def登录(用户) 登录后路径,:login=>user.login,:password=>password' 结束 设计用户注意事项。。。 顺便说一句,@davidchelimsky的答案可能需要一些调整,如果你正在使用。我在集成/请求测试中所做的工作(感谢):


FWIW,在将我的Test::unittests移植到RSpec时,我希望能够在我的请求规范中使用多个(设计)会话登录。这需要一些挖掘,但这对我来说是可行的。使用Rails 3.2.13和RSpec 2.13.0

# file: spec/support/devise.rb
module RequestHelpers
  def login(user)
    ActionController::IntegrationTest.new(self).open_session do |sess|
      u = users(user)

      sess.post '/users/sign_in', {
        user: {
          email: u.email,
          password: 'password'
        }
      }

      sess.flash[:alert].should be_nil
      sess.flash[:notice].should == 'Signed in successfully.'
      sess.response.code.should == '302'
    end
  end
end

include RequestHelpers
而且

# spec/request/user_flows.rb
require 'spec_helper'

describe 'User flows' do
  fixtures :users

  it 'lets a user do stuff to another user' do
    karl = login :karl
    karl.get '/users'
    karl.response.code.should eq '200'

    karl.xhr :put, "/users/#{users(:bob).id}", id: users(:bob).id,
      "#{users(:bob).id}-is-funny" => 'true'

    karl.response.code.should eq '200'
    User.find(users(:bob).id).should be_funny

    bob = login :bob
    expect { bob.get '/users' }.to_not raise_exception

    bob.response.code.should eq '200'
  end
end

编辑:修复了打字错误

您也可以很容易地将会话存根

controller.session.stub(:[]).with(:user_id).and_return(<whatever user ID>)
controller.session.stub(:[])。带有(:user_id.)和_return()

所有ruby特殊运算符实际上都是方法。调用
1+1
1.+(1)
相同,这意味着
+
只是一种方法。类似地,
session[:user\u id]
与调用
session
上的方法
[]
相同,就像
session.[](:user\u id)
我发现这对设计非常有帮助:

谢谢David。它工作得很好,但发出所有这些请求似乎有点过头了?如果我认为这是过头了,我就不会推荐它:)这也是可靠地完成任务的最简单方法
ActionDispatch::IntegrationTest
旨在模拟一个或多个用户通过浏览器进行交互,而无需使用真正的浏览器。一个示例中可能有多个用户(即会话)和多个控制器,会话/控制器对象是上次请求中使用的对象。在请求之前,您无权访问它们。我必须使用
page.driver.post
Capybara@IanYang
page.driver.post
可能是一种反模式,根据Jonas Nicklas的说法,当我在rspec模型规范中使用“login user1”时,我为#获取未定义的局部变量或方法“user_session_path”;这假设您在
config/routes.rb
文件中有
design_for:users
。如果你指定了一些不同的东西,你必须相应地调整你的代码。这对我来说很有效,但我不得不稍微修改一下。我将
'user[email]=>user.email
更改为
'user[username]=>user.username
,因为我的应用程序使用用户名作为登录名而不是电子邮件。您救了我,谢谢!这似乎是一个合理的解决方案。这在请求规范中不起作用,但仅在控制器规范中起作用。
controller.session.stub(:[]).with(:user_id).and_return(<whatever user ID>)