我要为我的自定义验证器编写规格,该验证器使用此链来检查与ActiveStorage关联的文件是否为txt:
return if blob.filename.extension.match?('txt')
通常,我可以通过此调用将其存根:
allow(attached_file).to receive_message_chain(:blob, :byte_size) { file_size }
Rubocop认为这是冒犯,并向我指出了文档:https://www.rubydoc.info/gems/rubocop-rspec/1.7.0/RuboCop/Cop/RSpec/MessageChain
我将必须为blob
和byte_size
声明double并将它们存根在单独的行中,最后用5行代码代替1行。
答案 0 :(得分:1)
为什么要避免对消息链进行存根?
我将不得不为blob和byte_size声明double并将其存根在单独的行中,最后以5行代码代替1。
实际上,这就是重点。在那有5条线可能会使您感到有些不安。这可以被认为是“正设计压力”。您的测试设置很复杂,它告诉您看一下实现。使用#receive_message_chains
使我们对预先暴露出复杂交互的设计感到满意。
RSpec的一位作者在GitHub issue中对此进行了解释。
我该怎么办?
一种选择是在测试的设置阶段将夹具文件附加到记录:
before do
file_path = Rails.root.join("spec", "fixtures", "files", "text.txt")
record.attribute.attach(io: File.open(file_path), filename: "text.txt")
end
这将对验证器进行端到端测试,而不会产生任何存根。
另一种选择是提取一个命名方法,然后对它进行存根。
在您的验证器中:
def allowed_file_extension?
blob.filename.extension.match?("txt")
end
在测试中:
before do
allow(validator).to receive(:allowed_file_extension?).and_return(true)
end
这还有一个额外的好处,就是通过命名一个概念使代码更加清晰。 (即使使用测试治具,也没有阻止您添加此方法的方法。)