如何使用 rspec 存根 env['warden'].user 以进行 ApplicationCable::Connection 测试

问题描述 投票:0回答:2

Rails 5.2 我有以下 ApplicationCable::Connection ruby 文件:

module ApplicationCable
  class Connection < ActionCable::Connection::Base

    identified_by :current_user

    def connect
      self.current_user = find_verified_user
    end

    private

    def find_verified_user
      if verified_user = env['warden'].user
        verified_user
      else
        message = "The user is not found. Connection rejected."
        logger.add_tags 'ActionCable', message  
        self.transmit error: message 
        reject_unauthorized_connection
      end
    end
  end
end

我想测试此设置并使用以下 RSpec 测试:

require 'rails_helper.rb'

RSpec.describe ApplicationCable::Connection, type: :channel do

  it "successfully connects" do
    connect "/cable", headers: { "X-USER-ID" => 325 }
    expect(connection.user_id).to eq 325
  end
end

失败的原因是:

失败/错误:如果verified_user = env['warden'].user

无方法错误: nil:NilClass

的未定义方法“[]”

所以我想删除 env['warden'].user 代码并返回 325 的 id。 我尝试了以下方法:

allow(env['warden']).to receive(:user).and_return(325)

但这产生了以下错误:

undefined local variable or method
环境'

我如何测试这门课?

rspec devise rspec-rails actioncable
2个回答
9
投票

试试这个:

require 'rails_helper.rb'

RSpec.describe ApplicationCable::Connection, type: :channel do

  let(:user)    { instance_double(User, id: 325) }
  let(:env)     { instance_double('env') }

  context 'with a verified user' do

    let(:warden)  { instance_double('warden', user: user) } 

    before do
      allow_any_instance_of(ApplicationCable::Connection).to receive(:env).and_return(env)
      allow(env).to receive(:[]).with('warden').and_return(warden)
    end

    it "successfully connects" do
      connect "/cable", headers: { "X-USER-ID" => 325 }
      expect(connect.current_user.id).to eq 325
    end

  end

  context 'without a verified user' do

    let(:warden)  { instance_double('warden', user: nil) }

    before do
      allow_any_instance_of(ApplicationCable::Connection).to receive(:env).and_return(env)
      allow(env).to receive(:[]).with('warden').and_return(warden)
    end

    it "rejects connection" do
      expect { connect "/cable" }.to have_rejected_connection
    end

  end
end

1
投票

这是对您的问题的一个很好的解释https://stackoverflow.com/a/17050993/299774

问题是关于控制器测试的,但它确实很相似。

我也不认为你应该在控制器中访问低级别

env['warden']
。如果 gem 作者决定改变这一点怎么办 - 你必须修复你的应用程序。 可能典狱长对象是使用此配置初始化的,并且应该有一个可用的对象(只是在运行规范时不需要 - 如上面的链接所述)。

© www.soinside.com 2019 - 2024. All rights reserved.