Share

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!

← Previous post: Restarting thin or passenger Rails server from Vim Next post: Testing domains with Rails and Test-Unit →
comments powered by Disqus