如何使用RSpec测试结合Devise的ActionCable连接?
Rails 5.1中使用action-cable-testing测试Devise认证的ActionCable连接问题
我来帮你搞定这个测试报错的问题!你遇到的NoMethodError是因为测试环境里env['warden']是nil,而你的连接代码还在尝试从这里取用户信息。下面给你两种可行的解决办法:
方法一:在测试中模拟Warden环境
你的连接逻辑依赖env['warden'].user来获取用户,但默认的stub_connection并没有帮你设置这个环境变量。所以我们需要手动模拟Warden对象并注入到连接的env中:
修改你的测试代码:
require 'rails_helper' RSpec.describe ApplicationCable::Connection, type: :channel do let(:user) { create(:user) } before do # 模拟warden实例,返回我们创建的测试用户 warden_double = double('Warden', user: user) # 将模拟的warden注入到连接的env中 stub_connection(env: { 'warden' => warden_double }) end it 'successfully connects' do expect { connect '/cable' }.to_not raise_error end end
这样你的find_verified_user方法就能正常通过env['warden'].user拿到用户,不会再触发nil的方法调用错误。
方法二:调整连接代码兼容测试场景
如果你希望测试代码保持简洁,也可以修改ApplicationCable::Connection里的find_verified_user方法,让它优先使用已经stub的current_user(测试场景),再回退到Warden的逻辑:
module ApplicationCable class Connection < ActionCable::Connection::Base identified_by :current_user def connect puts 'current_user:', current_user.inspect self.current_user = find_verified_user logger.add_tags 'ActionCable', current_user.id end def disconnect # ... end protected def find_verified_user # 优先取已设置的current_user(测试时stub的),否则从Warden获取 verified_user = current_user || env['warden'].user return verified_user if verified_user reject_unauthorized_connection end end end
这样原来的测试代码就可以正常运行了,不需要改动测试部分。
为什么原来的测试会报错?
你之前用stub_connection(current_user: user)只是给连接对象设置了current_user属性,但你的连接逻辑里并没有直接使用这个属性,而是仍然尝试从env['warden']获取用户。测试环境中这个env['warden']并没有被初始化,所以调用env['warden']时得到nil,再调用[]方法就触发了NoMethodError。
内容的提问来源于stack exchange,提问作者neversleep
相关产品推荐
相关产品推荐

