On Fri, Jan 06, 2006 at 04:20:00AM +0900, Sam J. wrote:
I was wondering about the class used when rails receives file uploads.
Sometimes it appears to be a File, and other times it is a StringIO.
Also it has methods such as original_filename that don’t appear to
belong to either of these classes. I ask because I’m trying to work out
how to test my fil upload related models and controllers.
Is there some standardised way of creating a file upload mock object?
Many thanks in advance.
Here’s some code for testing file uploads. This has some bits that are
specific
to the implementation so you can’t just copy and paste this wholesale
and
expect it to work but perhaps it can provide some direction.
In the test_helper.rb:
module UploadedFile
attr_accessor :original_filename, :content_type
end
def uploaded_file(contents, name, content_type)
io = StringIO.new(contents)
io.extend UploadedFile
io.original_filename = name
io.content_type = content_type
io
end
def empty_trash!
FileUtils.rm_rf(Dir["#{Upload.upload_root}/*"])
end
def file_uploaded?(file_name)
File.exists?(uploaded_file_path(file_name))
end
def assert_file_uploaded(file_name)
assert file_uploaded?(file_name)
end
def assert_file_not_uploaded(file_name)
assert !file_uploaded?(file_name)
end
def assert_upload_equals(contents, file_name)
assert_file_uploaded file_name
assert_equal contents, IO.read(uploaded_file_path(file_name))
end
def uploaded_file_path(file_name)
namespace =
Upload.namespace_directories(@controller.send(:account).id)
File.join(Upload.upload_root, namespace, file_name)
end
The functional tests look something like this:
def teardown
empty_trash!
end
def test_basic_upload
assert_difference_in_size(Upload) do
upload = uploaded_file(‘Rock out!’, ‘nsync.mp3’, ‘audio/mpg’)
post :new, :upload => upload
assert_file_uploaded ‘nsync.mp3’
assert_not_nil assigns(:upload).upload_message
end
end
def test_all_upload_metadata_set
upload = uploaded_file(‘La la la’, ‘jason-in-shower.mp3’,
‘audio/mpg’)
post :new, :upload => upload
record = assigns(:upload)
assert_equal ‘La la la’.size, record.byte_size
assert_equal ‘audio/mpg’, record.content_type
assert_equal ‘jason-in-shower.mp3’, record.name
end
And finally, though not central to testing the uploading specifically,
here is
assert_difference_in_size (which I pretty much use all the time
everywhere):
def assert_difference_in_size(object, methods = nil, difference = 1)
methods ||= :count
apply = Proc.new {|obj, methods|
[*methods].inject(object) {|result, method| result.send(method)}
}
initial_value = apply.call(object, methods)
yield
assert_equal initial_value + difference, apply.call(object, methods)
end
def assert_no_difference_in_size(object, methods = nil, &block)
assert_difference_in_size object, methods, 0, &block
end
Quack!
marcel