ruby-on-rails - 如何测试 ActiveSupport::TaggedLogging
问题描述
我想测试作为代码一部分生成的特定日志。虽然测试起来似乎相当简单Rails.logger
,但我将它包装在ActiveSupport::TaggedLogging
其中,我无法使用它进行测试......
这是我有的两种方法:
def logger
@logger = ActiveSupport::TaggedLogging.new(Rails.logger)
end
def log(message)
logger.tagged('MangaDex::Importer', "User ##{@current_user_id}") do
logger.info message
end
end
然后我在我的代码中这样调用它:
if md_parsed_list.blank?
log 'List is inaccessible'
return
end
现在,在我的 Rspec 测试中,我一直在尝试做这样的事情:
it 'logs and stops execution if there is nothing to import' do
expect(Spiders::Mangadex).to receive(:parse!)
.with(:parse, url: import_url)
.and_return({})
expect(ActiveSupport::TaggedLogging).to receive(Rails.logger)
expect(Rails.logger).to receive(:info).with('List is inaccessible')
expect(CreateMangaEntries).not_to receive(:call)
described_class.perform_async(import_url, user.id)
described_class.drain
end
我知道我在连接 TaggedLogging 和 Rails.logger 时缺少一些步骤,因为调用上面的测试只会引发错误undefined method 'to_sym' for #<ActiveSupport::Logger:0x00007f8fc545db50>
。
希望对此有所帮助,在此先感谢!
编辑:
在基于@Grzegorz 改进了所涉及的模拟之后,测试最终看起来像这样:
let(:tagged_logger_double) { instance_double(ActiveSupport::Logger) }
it 'logs and stops execution if MDList is inaccessible' do
expect(Spiders::Mangadex).to receive(:parse!)
.with(:parse, url: import_url)
.and_return(nil)
expect(ActiveSupport::TaggedLogging)
.to receive(:new)
.with(Rails.logger)
.and_return(tagged_logger_double)
expect(CreateMangaEntries).not_to receive(:call)
expect(tagged_logger_double).to receive(:info).with('List is inaccessible')
described_class.perform_async(import_url, user.id)
described_class.drain
end
由于存在的实例,我不得不稍微改变双ActiveSupport::TaggedLogging
精度ActiveSupport::Logger
。
我能够解决原始异常,但仍然无法测试receive(:info)
,因为tagged
似乎缺少:
#<InstanceDouble(ActiveSupport::Logger) (anonymous)> received unexpected message :tagged with ("MangaDex::Importer", "User #2626")
但是,当我也尝试对该方法进行存根时:allow(tagged_logger_double).to receive(:tagged)
,我得到了这种方法不存在的错误:the ActiveSupport::Logger class does not implement the instance method: tagged
,我仍然被失败的测试困住了。
解决方案
Grzegorz 正确回答了你问题的第一部分,所以从他离开的地方继续......
你是对的,你需要 stub tagged
。您收到方法未实现错误的原因是因为ActiveSupport::Logger
未实现tagged
. 它在被 包裹时被扩展ActiveSupport::TaggedLogging
。
在此处查看构造函数方法定义:https ://api.rubyonrails.org/classes/ActiveSupport/TaggedLogging.html#method-c-new
在这种情况下,我不确定如何使用验证替身。一种选择是不这样做,而只使用double
.
另一个问题是你没有tagged
正确存根。您需要对它进行存根,以便它屈服于块。
最后,您需要记住logger
方法的返回值,因为您只希望ActiveSupport::TaggedLogging
收到new
一次。
将所有这些结合在一起,我编写了以下测试:
require "rails_helper"
require "custom_logger"
RSpec.describe "CustomLogger" do
let(:tagged_logger_double) { double("Tagged logger") }
it "logs" do
expect(ActiveSupport::TaggedLogging)
.to receive(:new)
.with(Rails.logger)
.and_return(tagged_logger_double)
allow(tagged_logger_double)
.to receive(:tagged)
.and_yield
expect(tagged_logger_double).to receive(:info).with("message")
CustomLogger.new.log("message")
end
end
这通过以下代码传递,我认为这与您的示例非常相似:
class CustomLogger
def log(message)
logger.tagged("Tag") do
logger.info message
end
end
def logger
@_logger ||= ActiveSupport::TaggedLogging.new(Rails.logger)
end
end
推荐阅读
- pine-script - pine 脚本 if 和 then 语句
- c# - OTP和密码的字符串替换?
- html - Angular - 数组未显示在 mat-table 中
- javascript - JS在Callback中跳过函数
- c - 我可以在 c 编程语言中创建一个只有一位的变量吗?
- sql - SQL - 如何选择所有聊天并按最新消息排序
- javascript - odoo 14 Unhandled Promise done is not a function
- react-native - 如何修复 vue 原生核心版本错误?
- typescript - TypeScript:如何从另一个 scipt 访问变量?
- python - 将一列 unix 时间戳转换为日期