views:

136

answers:

2

What would be the correct way of unit testing a controller action that performs a redirect?

UPDATE: I'm a core developer on the CFWheels project. The whole reason I'm asking this question is currently I'm working on enhancing the built in testing framework we have and I'm wondering on how to approach and implement something like this in CFWheels to make it easier for developers to test their application.

UPDATE: I figured out how to test this. it seems that we will have to rewrite the wheels controller internals a bit to perform the redirect after the action completes and after it gets passed back to the dispatcher. the only thing with this approach is that any code after the redirectTo() would be ran EXCEPT if you take the appropriate precautions before hand; this includes either putting a return after the redirectTo() statement or putting conditional checks in your action to isolate the redirectTo() code from other code. It also involves making sure that nothing else is rendered once a redirectTo() is performed.

+2  A: 

You could call the controller with the appropriate URL using cfhttp with redirect set to false. Then test the resulting cfhttp result struct, it should have info about where the redirect would take you.

Terry Ryan
the only problem i see with this approach is that the test could run really slow. it would be better if i didn't have to issue a http request. one of the approaches i was thinking about was using an application variable with redirectTo() to return the arguments struct during testing and bypass the cflocation. my only problem is what would happen if there is other logic after the redirectTo(), that could would run.
rip747
I'd argue that if your controller is doing a redirect that takes too long for a unit test something is broken, unless I misunderstand what you're doing. In that case, set a timeout on cfhttp, and fail if it takes too long.
Terry Ryan
+1  A: 

Stuff like this becomes a whole lot easier to test if you break apart the redirect mechanism into multiple functions: a) a function that determines the target URL and b) a function that performs the redirect.

This way, you can test functionA very easily, and functionA is the one you want to test anyway. It's the code you wrote. It's where your real logic is. FunctionB is not your code; it's ColdFusion guts, and there's not much sense in testing CFLocation.

If you're on some mission to achieve 100% test coverage, then you could spend 10 tests for functionA where you exercise all the different branches of your logic, and then one test for functionB which exercises the redirect in the manner that Terry suggests; so in this manner, you only get 1 slow test instead of 10.

You can generalize this approach for uses in other scenarios: file systems, webservices, http, ftp, email, etc: "Extract the stuff you can control and want to test from the stuff you can't control and don't want to test"

marc esher