Uploading files in functional tests with Rails, Paperclip and Test Unit
I've been tearing my hair out for a couple of hours on this, so I thought I'd log the solution for everyone else's benefit!
The setup
I had a Rails 3 app with the paperclip gem installed, and I wanted to test file uploading in my controller (functional) test. I had an Image model, and an Images *controller. Paperclip was being applied to a field called *image on the model. The image was required, so a record could not be created without a file associated with it. Here's the model:
class Image < ActiveRecord::Base
validates :title, :description, :presence => true
validates :image, :attachment_presence => true
attr_accessible :description, :title, :image
has_attached_file :image, :styles => { :medium => "300x300>",
:thumb => "100x100>" }
end
The problem
File uploading was working on the frontend, but I couldn't figure out how to test the damn thing in my controller. I wanted to mimic a multipart form post with a test image, and create an image record with this test image. I tried passing the image attribute as a string, a File object, and all sorts of other horrific things, but to no avail.
I already had some scaffolded test code that would create the image, but it didn't do anything with the image attribute:
test "should create image" do
assert_difference('Image.count') do
post :create, image: { description: @image.description,
title: @image.title }
end
assert_redirected_to admin_image_path(assigns(:image))
end
This failed, because the image attribute is required.
The solution
So, how do you upload files in test unit? Use the helper method fixture_file_upload
and put your test file in the test/fixtures directory. Then just pass the name of this file to the fixturefileupload method, and it returns a file object which pretends to be an uploaded file, which Paperclip can handle.
The code looks like so:
test "should create image" do
image = fixture_file_upload 'gorilla.png'
assert_difference('Image.count') do
post :create, image: { description: @image.description,
title: @image.title,
image: image }
end
assert_redirected_to admin_image_path(assigns(:image))
end
Solved!