# Testing file uploads

**URL:** <https://www.ruby-forum.com/t/testing-file-uploads/51675>\
**Category:** Rails\
**Created:** [January 5, 2006, 8:21pm UTC](https://www.ruby-forum.com/t/testing-file-uploads/51675 "2006-01-05T20:21:35Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![samj](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/77aa72/32.png) [@samj](https://www.ruby-forum.com/u/samj)\
**Post date:** [January 5, 2006, 8:21pm UTC](https://www.ruby-forum.com/t/testing-file-uploads/51675/1 "2006-01-05T20:21:35Z")

</div>

Hi all,

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.

CHEERS\> SAM

---

<div class="post-metadata">

**Author:** ![samj](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/77aa72/32.png) [@samj](https://www.ruby-forum.com/u/samj)\
**Post date:** [January 8, 2006, 12:20am UTC](https://www.ruby-forum.com/t/testing-file-uploads/51675/2 "2006-01-08T00:20:12Z")

</div>

Hi Marcel,

Thanks - this is very helpful.

I also wonder is this the way that rails itself handles incoming files,  
i.e. it takes a StringIO or File object and uses the extend operation to  
add meta-data?

CHEERS\> SAM

---

<div class="post-metadata">

**Author:** ![samj](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/77aa72/32.png) [@samj](https://www.ruby-forum.com/u/samj)\
**Post date:** [January 6, 2006, 1:16am UTC](https://www.ruby-forum.com/t/testing-file-uploads/51675/3 "2006-01-06T01:16:06Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![samj](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/77aa72/32.png) [@samj](https://www.ruby-forum.com/u/samj)\
**Post date:** [January 8, 2006, 1:11am UTC](https://www.ruby-forum.com/t/testing-file-uploads/51675/4 "2006-01-08T01:11:19Z")

</div>

On Fri, Jan 06, 2006 at 04:20:00AM +0900, Sam J. wrote:

> Many thanks in advance.
> 
> CHEERS\> SAM

I do some basic file upload testing with this set up:

[http://rubyi.st/show/9](http://rubyi.st/show/9)

YMMV, of course, depending on the complexity you need.

-Scott

---

<div class="post-metadata">

**Author:** ![samj](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/77aa72/32.png) [@samj](https://www.ruby-forum.com/u/samj)\
**Post date:** [January 8, 2006, 12:56am UTC](https://www.ruby-forum.com/t/testing-file-uploads/51675/5 "2006-01-08T00:56:17Z")

</div>

On Sun, Jan 08, 2006 at 08:18:38AM +0900, Sam J. wrote:

> I also wonder is this the way that rails itself handles incoming files,  
> i.e. it takes a StringIO or File object and uses the extend operation to  
> add meta-data?

Rails isn’t responsible for any of this actually. It is ruby’s cgi.rb  
that  
handles file uploads and creating an IO object with metadata.

marcel
