Reputation: 43589
Given a non-trivial Rails application with significant numbers of controllers and routes only accessible to authenticated users and even then, only by users with the authorisation, what is the most sensible way to test unauthenticated users and unauthorised users are denied access?
Currently I generally test authenticated user flows through features, and fall back to controller tests to test that routes are not accessible to unauthorised or unauthenticated users.
Obviously ensuring that unauthenticated users get a 401 is easy enough to test, but testing authorisation is another matter. It makes sense to have granular tests for access permissions - I want to know if something I've done has inadvertently given a guest the ability to destroy users - but adding such tests for every root balloons the number of tests drastically.
How should I approach this?
Upvotes: 3
Views: 273
Reputation: 37607
It depends on how you do the authorization. You only need to write as many tests as you write blocks of code that authorize.
If you write specific code to check authorization every place a resource is used, there's no alternative but to write a test, probably a controller spec, for each check. I'd also write one Cucumber scenario to specify what the user sees when authorization is denied and to integration-test the entire stack.
If you move your authorization into a framework, whether something like Cancan or a framework of your own, that only requires each controller to call the framework in one place (e.g. CanCan's load_and_authorize_resource
), then you only need to write one more spec per controller (one that shows that some authenticated but unauthorized user can't access a resource) to establish that the authorization framework is being called. If the framework moves authorization logic to a new set of classes (e.g. CanCan::Ability
subclasses), you'll need to unit-test those classes, but you'll probably be able to use each such class in more than one place, so the number of tests they need won't increase multiplicatively, and their tests will be simpler than controller specs.
Similarly, if your authorization framework were entirely configuration-driven and you had to call it only in one place in your application, you'd only need to write that one Cucumber scenario.
You can probably think of different architectures which would lead to different testing requirements, but I think these examples show the general idea.
Upvotes: 1