开发者

Testing file uploads in Rails: can't convert ActionController::TestUploadedFile into String

Having problems testing a (working) upload in my Rails app (using 2.3.8):

class ProfilesControllerTest < ActionController::TestCase
  test "creates a new profile" do
    fixture_image = fixture_file_upload("#{RAILS_ROOT}/test/fixtures/files/avatar.jpg", 'image/jpeg')
    post :create, :profile=>{:username=>'johndoe', 
                             :password=>'mypass',
                             :avatar => fixture_image
                          }, :html => { :multipart => true }
    assert_response :success
    assert_not_nil Profile.find_by_username("johndoe")
    assert_not_nil Profile.find_by_username("johndoe").avatar
  end
end

The controller just assigns the params in bulk

@profile = Profile.new(params[:profile])
@profile.save

Model 开发者_开发技巧uses Joint to handle the uploads:

class Profile
  include MongoMapper::Document  
  plugin Joint

  attachment :avatar
end

Getting this error when running the test:

1) Error:
  test_creates_a_new_profile(Api::ProfilesControllerTest):
  TypeError: can't convert ActionController::TestUploadedFile into String
  (eval):15:in `size'
  (eval):15:in `avatar='
  /Users/oliver/.rvm/gems/ruby-1.8.7-p302/gems/mongo_mapper-0.8.6/lib/mongo_mapper/plugins/keys.rb:183:in `send'

What gives? Apparently the avatar= setter will deal with real uploaded files, but won't deal with TestUploadedFile's.


Maybe rails actioncontroller test upload file doesn't work for some reason with File.size?

This is the only line that deals with size: http://github.com/jnunemaker/joint/blob/master/lib/joint.rb#L46

Try doing File.size(...) where ... is the fixture file upload. See if that errors. If so, then maybe rails needs to be tweaked.

I actually use something like this often when testing file uploads:

def uploaded_file(path)
  pathname     = Rails.root + 'test/fixtures/' + path
  filename     = File.basename(path)
  tempfile     = Tempfile.new(filename)
  content_type = MIME::Types.type_for(pathname.to_s).to_s

  FileUtils.copy_file(pathname, tempfile.path)

  (class << tempfile; self end).class_eval do
    alias local_path path
    define_method(:original_filename) { filename }
    define_method(:content_type)      { content_type }
  end

  return tempfile
end

Not the prettiest but it gets the job done.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜