views:

255

answers:

3

I'm writing an upload function for ColdFusion of Wheels and need to unit test it once it's finished. The problem I'm having though is that I have no idea on how to create a mock multi-part form post in ColdFusion that I can use in my unit tests.

What I would like to be able to do is create the mock request simulating a file being uploaded that cffile could then process and I could check against.

I saw in the online ColdFusion help, an example of creating such a request using cfhttp, however it has to post to another page which kind of defeats that whole purpose.

+1  A: 

I did a quick search for MXUnit testing a form upload and came up with this google groups thread. http://tinyurl.com/ngwvgl

Its a discussion between Peter Bell and Bob Silverberg - the outcome of which is that testing a file upload is actually part of acceptance testing as opposed to a unit test.

I know that doesn't strictly answer your question, but I hope it helps.

Stephen Moretti
thank you for the reference. need to think about this a little more.
rip747
+3  A: 

Great question rip. For what it's worth, I contribute to MXUnit (wrote the eclipse plugin) and this scenario came up in a presentation I did at cfobjective this year on writing easier-to-test code (http://mxunit.org/doc/zip/marc%5Fesher%5Fcfobjective%5F2009%5Fdesigning%5Ffor%5Feasy%5Ftestability.zip).

In this scenario, I'd suggest NOT testing the upload. I believe we shouldn't spend time testing stuff that's not our code. The likelihood that we'll catch a bug or other oddity is sufficiently low for me to justify leaving it untested. I believe we should be testing "our" code, however.

In your scenario, you have two behaviors: 1) the upload and 2) the post-upload behavior. I'd test the post-upload behavior.

This now frees your unit test to not care about the source of the file. Notice how this actually results in a decoupling of the upload logic from the "what do I do with the file?" logic. Taken to its conclusion, this at least creates the potential (theoretically) to reuse this post-upload logic for stuff other than just uploads.

This keeps your test much easier, because now you can just test against some file that you put somewhere in the setUp of the unit test itself.

So your component changes from

<cfffunction name="uploadAndDoStuff">

to

 <cffunction name="upload">

and then

<cffunction name="handleUpload">

or "handleFile" or "doSomethingWithFile" or "processNetworkFile" or some other thing. and in your unit test, you leave upload() untested and just test your post-upload handler. For example, if I were doing this at work, and my requirements were: "Upload file; move file to queue for virus scanning; create thumbnails if image or jpg; add stuff to database; etc" then I'd keep each of those steps as separate functions, and I'd test them in isolation, because I know that "upload file" already works since it's worked since CF1.0 (or whatever). Make sense?

Better yet, leave the "upload" out of the component entirely. nothing wrong with keeping it in a CFM file since there's kind of not much point (as far as I can see) in attempting to genericize it. there might be benefits where mocking is concerned, but that's a different topic altogether.

marc esher
A: 

Strictly speaking you are right. If you have to go out to make a call to an external resource do test something ( database, web service, file uploader) it does defeat the purpose of unit testing. The best general advice is to mock out behaviours of external resources and assume they function or are covered by their own unit tests.

Pragmatism can alter this though, on the Model-Glue framework codebase, we have a number of unit tests that call out to external resources, like for persisting values across a redirect, connecting the AbstractRemotingService functionality and so on. These were deemed important enough features to unit test and we chose to make external dependencies of our unit tests to ensure good coverage. After all, in framework code, there IS NOT acceptance tests. Those are done by our users and users of a framework expect flawless code, as they should.

So there are cases where you want to test a vital external resource and you want it handled by an automated function, it can make sense to add it to your unit tests. Just know you are deviating away from a best practice that is there for a reason.

Dan Wilson

Dan Wilson