Rspec 遇上 Active Storage。
项目里文件上传部分使用了activestorage,写Rspec时,一直报错ActiveSupport::MessageVerifier::InvalidSignature,看文档查ActiveSupport::MessageVerifier::InvalidSignature, 懵逼,小坑,最后依靠强大的stack overflow解决了,记录下。
场景:
现有model attachment,含有字段file,title,另有一个model issue,issue与attachment是一对多的关系。
在app/models/attachment.rb
中,添加了:
class Attachment < ApplicationRecord
belongs_to :issue, optional: true
has_one_attached :file
end
在app/models/issue.rb
中,添加了:
class Issue < ApplicationRecord
has_many :attachments, dependent: :destroy
accepts_nested_attributes_for :attachments, allow_destroy: true
end
使用Rspec做测试时,用factorybot给Attachment建立测试数据,把测试使用的图片存放在spec/resources
下,其中spec/factories/attachments.rb
中的内容如下:
FactoryBot.define do
factory :attachment do
file { Rack::Test::UploadedFile.new(Rails.root.join("spec", "resources", "image.jpg") }
title "this is a title"
end
end
这里通过Rack ::Test::UploadedFile构建了file,这样在controller的spec中,传递给params的file就会被视为一个上传的文件。
现在需要测试issue中添加了attachment的场景。
在spec/controllers/issues_controller_spec.rb
中,有这样一段:
RSpec.describe IssuesController, type: :controller do
let!(:issue) { create :issue }
let(:issue_attributes) { {} }
.....
describe "PUT update issue" do
action { put :update, params: { id: issue, issue: issue_attributes } }
context "with attachment" do
let!(:attachment) { create :attachment, issue: issue }
it expect(issue.attachments.count).to eq 1
end
......
end
end
此时运行,会报错,显示:
Failures:
1) IssuesController PUT update issue with attachment should not be nil
Failure/Error: @issue.update(issue_params)
ActiveSupport::MessageVerifier::InvalidSignature:
ActiveSupport::MessageVerifier::InvalidSignature
如果你在issues_controller.rb
的issue_params中设置断点,会发现attachment虽然创建成功,但是attachment的file为空,也就是active storage并没有创建对应的blob, file并没有成功attached,可以通过attachment.file.attached?
来判断file是否已经attached。
解决方法
最后找到的解决的方法其实很简单,来自stack overflow上How to properly do model testing with ActiveStorage in rails?, 只要修改一下attachment测试数据的生成方式即可,修改spec/factories/attachments.rb
:
FactoryBot.define do
factory :attachment do
title "this is a title"
after(:build) do |attachment|
attachment.file.attach(io: File.open(Rails.root.join("spec", "resources", "image.jpg")), filename: 'image.jpg', content_type: "image/jpg")
end
end
end
再次跑测试,会发现通过了。
参考
Active Storage raises ActiveSupport::MessageVerifier::InvalidSignature
How to properly do model testing with ActiveStorage in rails?