Testing Carrierwave with Fog for Amazon S3


07-17-2012


Filed under: mocking, rails, rspec, carrierwave, fog, s3

Testing file upload using CarrierWave with Fog with S3 turns out to be difficult.

First, create config/fog_credentials.yml

default:
  aws_access_key_id: 'your-aws-access-key-id'
  aws_secret_access_key: 'your-aws-secret-access-key/'
  region: 'your-aws-region'

Next, put this to your config/initializers/carrier_wave.rb

Fog.credentials_path = Rails.root.join('config/fog_credentials.yml')

fog_dir = Rails.env == 'production' ? 'production-bucket' : 'dev-bucket'

CarrierWave.configure do |config|
  config.fog_credentials = {:provider => 'AWS'}
  config.fog_directory  = fog_dir
end

Next, put this into spec/support/fog_helper.rb

Fog.mock!
Fog.credentials_path = Rails.root.join('config/fog_credentials.yml')
connection = Fog::Storage.new(:provider => 'AWS')
connection.directories.create(:key => 'dev-bucket')

Note, the :key value must match whats defined for fog_dir (dev-bucket) in carrier_wave.rb

Suppose you want to test this class:

class FileUploader < CarrierWave::Uploader::Base
  storage :fog
end

Your rspec test can be something like this:

class TestFileUploader
  mount_uploader :file, FileUploader
end

describe FileUploader do
  include FakeFS::SpecHelpers

  context 'for non-production environment' do
    it 'should upload video clip to dev-bucket on s3' do
      FakeFS.activate!
      FakeFS::File.should_receive(:chmod) #this is needed or you will get an exception
      File.open('test_file', 'w') do |f|
        f.puts('foo') # this is required or uploader_test.file.url will be nil
      end
      uploader_test = TestFileUploader.new
      uploader_test.file = File.open('test_file')
      uploader_test.save!
      uploader_test.file.url.should match /.*\/dev-bucket.*/ #test to make sure that it is not production-bucket
      FakeFS.deactivate!
    end
  end
end

Now the test is complete. It uses fakefs to generate a fake file which is non-empty. Fog will pretent to upload the file using the FileUploader under test. The upload url is the subject under test.