Ruby on rails 如何测试ActiveSupport::TaggedLogging

Ruby on rails 如何测试ActiveSupport::TaggedLogging,ruby-on-rails,logging,rspec,ruby-on-rails-6,Ruby On Rails,Logging,Rspec,Ruby On Rails 6,我想测试作为代码一部分生成的特定日志。虽然测试Rails.logger似乎相当简单,但我将其包装在ActiveSupport::taggedloging中,我在测试时遇到了麻烦 我有两种方法: def记录器 @logger=ActiveSupport::TaggedLogging.new(Rails.logger) 结束 def日志(消息) taged('MangaDex::Importer','User##{@current_User_id})do logger.info消息 结束 结束 然

我想测试作为代码一部分生成的特定日志。虽然测试
Rails.logger
似乎相当简单,但我将其包装在
ActiveSupport::taggedloging
中,我在测试时遇到了麻烦

我有两种方法:

def记录器
@logger=ActiveSupport::TaggedLogging.new(Rails.logger)
结束
def日志(消息)
taged('MangaDex::Importer','User##{@current_User_id})do
logger.info消息
结束
结束
然后我在我的代码中这样调用它:

如果md_已解析_list.blank?
日志“列表不可访问”
返回
结束
现在,在我的Rspec测试中,我一直在尝试这样做:

如果没有要导入的内容,它会记录并停止执行
期望(spider::Mangadex).接收(:parse!)
.with(:parse,url:import\u url)
.和_返回({})
期望(ActiveSupport::TaggedLogging).接收(Rails.logger)
期望(Rails.logger).接收(:info).with('列表不可访问')
期望(CreateMangaEntries).不接收(:调用)
描述了\u类。执行\u异步(导入\u url,user.id)
描述了U类排水管
结束
我知道我在连接TaggedLogging和Rails.logger时遗漏了一些步骤,因为调用上面的测试只会为#抛出一个错误
未定义的方法

希望能得到一些帮助,提前谢谢

编辑:

改进了基于@Grzegorz的模拟后,测试结果如下:

let(:taged_logger_double){instance_double(ActiveSupport::logger)}
如果MDList不可访问,它会记录并停止执行
期望(spider::Mangadex).接收(:parse!)
.with(:parse,url:import\u url)
.和_返回(无)
expect(ActiveSupport::TaggedLogging)
.接收(:新)
.with(Rails.logger)
.和_返回(标记为_logger _double)
期望(CreateMangaEntries).不接收(:调用)
预期(已标记的\u logger\u double).接收(:info).with('列表不可访问')
描述了\u类。执行\u异步(导入\u url,user.id)
描述了U类排水管
结束
由于
ActiveSupport::taggedloging
的实例是
ActiveSupport::Logger
,因此我不得不稍微更改double

我能够解决原始异常,但仍然无法测试
receive(:info)
,因为
taged
似乎丢失了:
#收到意外消息:标记为(“MangaDex::Importer”,“User”#2626”)


但是当我尝试同时存根该方法时:
allow(taged\u logger\u double)。要接收(:taged)
,我会得到这样一个错误,即这样的方法不存在:
ActiveSupport::logger类没有实现实例方法:taged
,hene我仍然被一个失败的测试所困扰。

您已将一个对象传递给
。以接收
方法,该方法需要一个方法名(字符串或符号)。这就是您的错误来源,下面的内容对我来说更有意义:

expect(ActiveSupport::TaggedLogging)
  .to receive(:new)
  .with(Rails.logger)
  .and_return(tagged_logger_double)
然后,如果您这样定义记录器,您将可以完全访问规范中的记录器

let(:tagged_logger_double) { instance_double(ActiveSupport::TaggedLogging) }
设定你的期望

expect(tagged_logger_double).to receive(:info).with('List is inaccessible')

Grzegorz正确地回答了你问题的第一部分,所以要继续他刚才所说的

你是对的,你需要存根
标记
。您得到方法未实现错误的原因是
ActiveSupport::Logger
未实现
taged
。当通过
ActiveSupport::TaggedLogging
包装时,它会被扩展

请参见此处的构造函数方法定义:

我不知道在这种情况下如何使用双重验证。一种选择是不这样做,只需使用
双精度

另一个问题是,您没有正确地将
标记为
。您需要将其存根以使其屈服于块

最后,您需要记住
logger
方法的返回值,因为您只希望
ActiveSupport::taggedloging
接收
new
一次

综合所有这些,我编写了以下测试:

需要“rails\u助手”
需要“自定义记录器”
RSpec.description“CustomLogger”do
let(:taged_logger_double){double(“taged logger”)}
它是“日志”吗
expect(ActiveSupport::TaggedLogging)
.接收(:新)
.with(Rails.logger)
.和_返回(标记为_logger _double)
允许(标记的\u记录器\u双)
.接收(:标记)
.和_收益率
预期(标记为双)。接收(:信息)。带有(“消息”)
CustomLogger.new.log(“消息”)
结束
结束
这与下面的代码一起传递,我认为这与您的示例中的代码非常相似:

class自定义记录器
def日志(消息)
logger.taged(“Tag”)do
logger.info消息
结束
结束
def记录器
@_logger | |=ActiveSupport::TaggedLogging.new(Rails.logger)
结束
结束

这是一个很好的观点,这是定义期望的正确方法。但这并不是解决这个问题的全部办法。我现在无法从
记录器中将
标记为记录器。标记器
现在是
nil
。我假设我需要在那里传递一个double,而不是一个logger,然后只传递stub方法,但是我需要以某种方式将它注入代码中,我不完全确定这一点。对不起,我假设在从即时错误中解除阻塞后,您可以继续。我更新了我的答案,希望能有所帮助。谢谢@Grzegorz,嘲笑不是我的强项。你扩展的答案确实有帮助,但我又被卡住了。首先,有趣的是,taged
Logger
的实例变成了
ActiveSupport::Logger
,因此我必须更新
taged\u Logger\u double
。但现在我无法访问
receive(:info)
,因为我缺少
标记的
#收到了意外消息:标记为(“MangaDex::Importer”,“User#2626”)
,但当我尝试存根时