Testing an Uploaded File in Rspec
Uploading a file without actually uploading it
People Apple Desk by Lee Campbell is licensed under CC0
I recently wrote a unit test for a bit of code that saves an uploaded file from a controller to the database before pushing it off to a job. I had an example file in
spec/fixtures that I wanted to use. Throwing code at the wall, I came up with:
# Does not work! file = File.new(Rails.root.join("spec/fixtures/filename.xlsx")) save_uploaded_file_to_db(file)
#save_uploaded_file_to_db gets the parts of the file that we care about, and saves it to the database.
def save_uploaded_file_to_db(file) Upload.create( filename: File.basename(file.original_filename), content_type: file.content_type, data: file.read, ) end
Looks pretty straightforward, but I got a
NoMethodError when calling
original_filename. Turns out, this method is unique to
UploadedFile. That brought me to the question: “How can I have an uploaded file without uploading something?” I have the answer for you.
Why not instantiate the uploaded file the way we did the file?
file = Rack::Test::UploadedFile.new(Rails.root.join("spec/fixtures/filename.xlsx")) save_uploaded_file_to_db(file)
Well, that was easy, but it’s not very pretty. Thankfully, there’s a helper method we can use to clean it up. If you have
ActionDispatch::TestProcess::FixtureFile included, you can use
fixture_file_upload to create an upload file from a file in your test fixtures.
include ActionDispatch::TestProcess::FixtureFile file = fixture_file_upload("filename.xlsx") save_uploaded_file_to_db(file)
Easy enough. Then, you can use
file the way you were treating your uploaded file. Happy testing!