Rails控制器new方法RSpec测试断言失败问题求助
问题解决:RSpec测试Rails控制器assigns返回nil
问题场景
控制器代码:
def new @map_id = 1 puts @map_id end
RSpec测试代码:
describe 'GET #new' do it 'simplified test' do get :new expect(assigns(:map_id)).to eq(1) end end
运行测试报错:
Failure/Error: expect(assigns(:map_id)).to eq(1) expected: 1 got: nil (compared using ==)
已知:控制台运行方法能输出1,路由通过rails routes确认正确,文件命名规范,其他测试和路由正常。
原因分析
RSpec Rails从3.5版本开始,默认禁用了assigns和template这类控制器测试辅助方法,官方更推荐测试控制器的行为输出而非内部实例变量,这就是assigns(:map_id)返回nil的核心原因。
解决方案
方案1:重新启用assigns支持
在spec/rails_helper.rb中添加以下配置,全局启用控制器测试的辅助方法:
RSpec.configure do |config| # 启用控制器测试的辅助方法(包括assigns) config.include Rails::Controller::Testing::TestProcess config.include Rails::Controller::Testing::TemplateAssertions config.include Rails::Controller::Testing::Integration end
添加后重新运行测试,assigns(:map_id)即可正确获取实例变量的值。
方案2:使用RSpec推荐的测试方式(替代assigns)
官方不建议直接测试实例变量,推荐测试控制器的实际输出(比如响应内容、重定向路径等)。如果new方法会渲染视图并使用@map_id,可改为测试视图内容:
假设视图new.html.erb包含:
<p>Map ID: <%= @map_id %></p>
测试代码修改为:
describe 'GET #new' do it 'displays the correct map id' do get :new expect(response.body).to include('Map ID: 1') end end
这种方式更贴近用户实际体验,也符合RSpec的测试理念。
内容的提问来源于stack exchange,提问作者Dennis Christman
相关产品推荐
相关产品推荐

