Testing carrierwave file uploads with RSpec and FactoryGirl
Bài đăng này đã không được cập nhật trong 7 năm
Bài viết được dịch từ blog: https://til.codes/testing-carrierwave-file-uploads-with-rspec-and-factorygirl/
Trong bài viết này tác giả chỉ muốn tập trung vào việc sử dụng Carriewavve trong testing mà cụ thể là Rspec. Vì vậy nếu các bạn muốn biết cách cài đặt hoặc cấu hình carrierwave cho project của mình thì các bạn nên tham khảo trong wiki của carrierwave tại đây
Giả sử mọi thứ đã được cài đặt đầy đủ cho project của bạn, chúng ta có một model Attachment
sử dụng Carrierwave uploader(FileUploader
) như dười đây:
# app/models/attachment.rb
class Attachment < ActiveRecord::Base
mount_uploader :file, FileUploader
end
Để bắt đầu sử dụng trong testing, chúng ta cần tạo ra các bản ghi Attachment trong testing. Vì vậy chúng ta cần cập nhật factory của Attachment như sau:.
# spec/factories/attachments.rb
FactoryGirl.define do
factory :attachment do
photo Rack::Test::UploadedFile.new(File.open(File.join(Rails.root, '/spec/fixtures/myfiles/myfile.jpg')))
end
end
Trong đoạn code trên chúng ta đã đính kèm file trong thuw mục /spec/fixtures/myfiles/ folder
vào trường photo. Có một chú ý là đoạn code trên chỉ có tác dụng đính kèm một file vào trường photo khi bạn build một object mới. Nếu bạn sử dụng phương thức create
và muốn tạo một bản ghi tồn tại thực sự trong DB thì ta cần cập nhật đường dẫn file vào cột photo như sau:
FactoryGirl.define do
factory :attachment do
after :create do |b|
b.update_column(:photo, "foo/bar/baz.png")
end
end
end
Với tất cả các cài đặt ở trên thì ta đã đủ để sử dụng factory của Attachment trong Rspec như tất cả các model bình thường để testing. Tuy nhiên, sau đây tác giả sẽ trình bày thêm cách tối ưu để thời gian chạy test là nhanh nhất
- Cài đặt kiểu storage là file đối với môi trường test. 2.Loại bỏ quá trình xử lý file với môi trường test.
- Phân tách thư mục lưu file cho môi trường test khác các môi trường khác.
- Xóa file đã upload sua mỗi request.
Cài đặt Carrierwave để sử dụng local storage and disable quá trình xử lý file test env
Để làm được các công việc trên, chúng ta sẽ thêm cấu hình của Carrierwave trong thư mục initializer
như sau:
# config/initializers/carrierwave.rb
if Rails.env.test? || Rails.env.cucumber?
CarrierWave.configure do |config|
config.storage = :file
config.enable_processing = false
end
end
Phân tách thư mục chứa file của môi trường test khác với các môi trường khác.
Tiếp theo, chúng ta nên chia thư mục chứa file upload của môi trường test riêng biệt với các môi trường khác (production, development....). Chúng ta có thể sửa các phương thức cache_dir
và store_dir
cho tất cả các Carrierwave models hoặc ghi đè trong file config của initializers
như dưới đây:
# config/initializers/carrierwave.rb
CarrierWave::Uploader::Base.descendants.each do |klass|
next if klass.anonymous?
klass.class_eval do
def cache_dir
"#{Rails.root}/spec/support/uploads/tmp"
end
def store_dir
"#{Rails.root}/spec/support/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
end
Xóa file sua mỗi request.
Thêm đoạn code sau vào file spec_helper.rb
để chắc chắn rằng file sẽ được xóa sau mỗi test:
# spec_helper.rb
RSpec.configure do |config|
config.after(:each) do
if Rails.env.test? || Rails.env.cucumber?
FileUtils.rm_rf(Dir["#{Rails.root}/spec/support/uploads"])
end
end
end
Cài đặt asset_host
Ta nên cài đặt asset_host cho carrierwave trong file # config/initializers/carrierwave.rb
như sau:
CarrierWave.configure do |config|
config.asset_host = ActionController::Base.asset_host
end
Đến đây, ta đã hoàn thành việc cấu hình sử dungh carrierwave trong testing. Nội dung cuối cùng của file config/initializers/carrierwave.rb
sau khi chỉnh sửa là:
if Rails.env.test? || Rails.env.cucumber?
CarrierWave.configure do |config|
config.storage = :file
config.enable_processing = false
end
# make sure uploader is auto-loaded
FileUploader
CarrierWave::Uploader::Base.descendants.each do |klass|
next if klass.anonymous?
klass.class_eval do
def cache_dir
"#{Rails.root}/spec/support/uploads/tmp"
end
def store_dir
"#{Rails.root}/spec/support/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
end
end
CarrierWave.configure do |config|
config.asset_host = ActionController::Base.asset_host
end
Trên đây là cách sử dụng carrierwave trong factory girl và rspec. Cảm ơn các bạn đã dành thời gian theo dõi bài viết và hy vọng nó sẽ giúp ích trong công việc của mọi người.
All rights reserved