如何存根env[';warden';].ApplicationCable::Connection tests with rspec的用户

如何存根env[';warden';].ApplicationCable::Connection tests with rspec的用户,rspec,devise,rspec-rails,actioncable,Rspec,Devise,Rspec Rails,Actioncable,轨道5.2 我有以下ApplicationTable::Connection ruby文件: module ApplicationCable class Connection < ActionCable::Connection::Base identified_by :current_user def connect self.current_user = find_verified_user end private def

轨道5.2 我有以下ApplicationTable::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
它失败于:

失败/错误:如果已验证_user=env['warden']。用户

命名错误: nil:NilClass的未定义方法“[]”

所以我想去掉env['warden'].用户代码并返回一个325的id。 我尝试了以下方法:

allow(env['warden']).to receive(:user).and_return(325)
但这产生了以下错误:

未定义的局部变量或方法
env'

如何测试这个类?

试试这个:

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

这是对你的问题的一个很好的解释

问题是关于控制器测试的,但实际上是类似的

我也不认为您应该访问控制器中的低级
env['warden']
。如果gem的作者决定改变这一点,你将不得不修复你的应用程序。
可能warden对象是使用此配置初始化的,并且应该有一个可用的对象(只是在运行规范时不需要,如上面的链接所述)。

谢谢您的代码。我尝试了这一点,得到了以下错误:NameError:uninitialized constant ConnectionUpdated<代码>连接应该是
应用程序表::连接
。另外,我修复了
env
mock的另一个问题。我做了更改,现在我得到的是ApplicationTable::Connection未实现:envI已使用我根据您的答案修改的代码编辑了您的答案,以通过测试。我还不知道如何解决这件臭气熏天的事。这两项测试现在如预期的那样通过了。我希望你不介意我编辑你写的代码。很高兴你能工作!而且,我很高兴我能帮上忙!我不担心那气味。众所周知,控制器(显然还有电缆)很难模拟,因为Rails控制实例化,所以您不能注入测试双精度。这就是为什么RSpec有
允许任何
实例的原因。对不起,我一直提到控制器,这是关于动作电缆的。但从概念上讲,这些是同一层,所以在我看来,我们可以使用控制器的“概念”来讨论它们。谢谢。我已经根据许多站点(如)上概述的实践设置了ApplicationTable::Connection。我只是想知道是否有一种方法可以通过去掉这个方法来测试它。我认为你发送的链接是相关的,可能是我无法进行此测试的原因。
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