请求头处理模块的RSpec测试失败,求正确测试代码方案
解决ApiHelper模块的RSpec测试失败问题
问题背景
编写了用于处理第三方API请求头的ApiHelper模块,对应的RSpec测试始终失败,无法验证请求头的设置逻辑。
原模块代码
module ApiHelper def self.get_header(header) @request['Accept'] = header[:accept].blank? ? 'application/json' : header[:accept] @request['Content-Type'] = header[:content_type].blank? ? 'application/json' : header[:content_type] end end
原测试代码
describe '.get_header' do let(:request) { double('request') } before do allow(ApiHelper).to receive(:get_header).and_call_original allow(ApiHelper).to receive(:instance_variable_get).and_return(request) allow(request).to receive(:[]=) end context 'when header values are provided' do let(:header) { { accept: 'application/json', content_type: 'application/json' } } it 'sets the Accept and Content-Type header values' do ApiHelper.get_header(header) expect(request).to have_received(:[]=).with('Accept', 'application/json') # expect(request).to have_received(:[]=).with('Content-Type', 'application/json') end end context 'when header values are not provided' do let(:header) { {} } it 'sets default values for the Accept and Content-Type headers' do ApiHelper.get_header(header) expect(request).to have_received(:[]=).with('Accept', 'application/json') expect(request).to have_received(:[]=).with('Content-Type', 'application/json') end end end
测试失败信息
Failures: 1) ApiHelper.get_header when header values are provided sets the Accept and Content-Type header values Failure/Error: expect(request).to have_received(:[]=).with('Accept', 'application/json') (Double "request").[]=("Accept", "application/json") expected: 1 time with arguments: ("Accept", "application/json") received: 0 times # ./spec/helpers/api_helper_spec.rb:41:in `block (4 levels) in <top (required)>' 2) ApiHelper.get_header when header values are not provided sets default values for the Accept and Content-Type headers Failure/Error: expect(request).to have_received(:[]=).with('Accept', 'application/json') (Double "request").[]=("Accept", "application/json") expected: 1 time with arguments: ("Accept", "application/json") received: 0 times # ./spec/helpers/api_helper_spec.rb:51:in `block (4 levels) in <top (required)>' Finished in 0.23741 seconds (files took 1.39 seconds to load) 4 examples, 2 failures
失败原因分析
原测试试图通过 stub instance_variable_get 方法来返回mock的request对象,但实际模块的get_header方法是直接访问@request类实例变量,并没有调用instance_variable_get方法。这个stub完全没生效,导致代码中的@request为nil,自然不会触发[]=方法调用,测试断言失败。
修复后的测试代码
describe '.get_header' do let(:request) { double('request') } before do allow(ApiHelper).to receive(:get_header).and_call_original # 直接给ApiHelper设置@request实例变量,替代无效的stub ApiHelper.instance_variable_set(:@request, request) allow(request).to receive(:[]=) end context 'when header values are provided' do let(:header) { { accept: 'application/json', content_type: 'application/json' } } it 'sets the Accept and Content-Type header values' do ApiHelper.get_header(header) expect(request).to have_received(:[]=).with('Accept', 'application/json') expect(request).to have_received(:[]=).with('Content-Type', 'application/json') end end context 'when header values are not provided' do let(:header) { {} } it 'sets default values for the Accept and Content-Type headers' do ApiHelper.get_header(header) expect(request).to have_received(:[]=).with('Accept', 'application/json') expect(request).to have_received(:[]=).with('Content-Type', 'application/json') end end end
修复说明
- 用
ApiHelper.instance_variable_set(:@request, request)直接给模块设置类实例变量,确保get_header方法能访问到mock的request对象 - 移除了无效的
allow(ApiHelper).to receive(:instance_variable_get).and_return(request)代码 - 恢复了第二个断言(注释掉的Content-Type验证),确保完整覆盖逻辑
修复后运行测试,两个场景都会通过,验证请求头的设置逻辑符合预期。
内容的提问来源于stack exchange,提问作者HM Tanbir
相关产品推荐
相关产品推荐

