如何为带标签日志编写RSpec?断言时方法被Mock而非Stub/Spy的问题
问题解决方法
错误原因是have_received断言要求目标对象是**Spy(间谍)**或被存根的对象,而你当前的Rails.logger是Mock对象,Mock不会记录方法调用的详情,无法满足断言需求。
解决步骤:
- 先将
Rails.logger转为Spy对象,在测试开始前添加存根或直接替换为spy实例:# 方法1:用allow存根,自动转为Spy allow(Rails.logger).to receive(:info) # 方法2:直接替换为spy实例 Rails.logger = spy('Logger') - 另外注意:代码里的
Time.zone.now在执行和断言时的时间会有偏差,直接对比哈希会失败,要用时间匹配器模糊校验。
修正后的完整测试代码:
# 测试前置:将logger转为Spy before do allow(Rails.logger).to receive(:info) end it 'logs mail details correctly' do # 执行触发logger.info的代码 logger.tagged(mail.message_id) do logger.info({ to: Array(mail.to).join(', '), from: mail.from, subject: mail.subject, time: Time.zone.now, headers: mail.header, errors: mail.errors, delivery_status_part: mail.delivery_status_part, message_id: mail.message_id }) end # 断言时用时间匹配器处理time字段 expect(Rails.logger).to have_received(:info).with(hash_including( to: Array(mail.to).join(', '), from: mail.from, subject: mail.subject, time: be_within(1.second).of(Time.zone.now), headers: mail.header, errors: mail.errors, delivery_status_part: mail.delivery_status_part, message_id: mail.message_id )) end
说明:
allow(Rails.logger).to receive(:info)会把logger变成Spy,记录所有info方法的调用参数,让have_received能正常工作。hash_including用来校验哈希的指定字段,配合be_within处理时间的微小差异,避免因时间戳不一致导致断言失败。
内容的提问来源于stack exchange,提问作者Priya Lorha
相关产品推荐
相关产品推荐

