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.
精彩评论