Minitest测试调用ApplicationController方法实例变量不生效如何解决
错误根源
- 你当前使用的
ActionDispatch::IntegrationTest属于集成测试类,本身没有继承控制器,直接调用user_operator?自然会报方法不存在的错误——这个方法是定义在ApplicationController中的,不是测试类的实例方法。 - 你能读到的
@operator_roles是测试类自己的实例变量(大概率是你在setup环节手动赋值的),并不是控制器运行后生成的变量。@cu_rsu为nil是因为控制器的before_action :set_site全程没有被触发,自然不会执行current_user_role方法完成赋值。
解决方案
方案1:改用控制器单元测试直接验证逻辑
如果只需要验证控制器的方法逻辑,不需要走完整的请求链路,用控制器测试更轻量合适:
require 'test_helper' class ApplicationControllerTest < ActionController::TestCase tests ApplicationController # 明确指定测试的控制器 test 'current_user role' do @operators.each do |roleshopuser| sign_in roleshopuser.user # 传入shop_id参数,调用任意控制器公开action,自动触发before_action get :你控制器中存在的公开action名, params: { shop_id: @shop.id } # 用assigns读取控制器运行后生成的实例变量 assert_not_nil assigns(:cu_rsu) assert_equal roleshopuser.id, assigns(:cu_rsu).id assert_equal true, assigns(:user_operator) end end end
注意:Rails 5+ 版本如果要读取控制器实例变量,也可以直接访问controller实例获取:@controller.instance_variable_get(:@user_operator)
方案2:集成测试中触发真实请求
如果必须使用集成测试,需要先发起一个走ApplicationController的真实请求,让Rails自动执行before_action逻辑:
require 'test_helper' class ApplicationControllerTest < ActionDispatch::IntegrationTest test 'current_user role' do @operators.each do |roleshopuser| sign_in roleshopuser.user # 发起你的应用中存在的、带shop_id参数的请求,比如店铺详情页 get shop_path(@shop) # 通过测试类内置的@controller实例访问控制器内部方法和变量 assert_equal true, @controller.user_operator? assert_not_nil @controller.instance_variable_get(:@cu_rsu) end end end
内容的提问来源于stack exchange,提问作者Jerome
相关产品推荐
相关产品推荐

