Unit Testing MonoRail Controllers with PrincipalPermissions
When you apply a CodeAccessSecurityAttribute that returns a PrincipalPermission to an action on a controller, all your existing tests for that action will break (to find out more about applying principal permissions, take a look at this blog entry about creating clean principal permission attributes). After a bit of digging and a lot of googling, I came across this post by Phil Haack that demonstrates how to set up your unit tests so they run correctly again.
Phil’s approach uses Rhino Mocks to mock out the IPrincipal and IIdentity interfaces and then attaches the mocked IPrincipal to Thread.CurrentPrincipal (which is where the PrincipalPermission retrieves the principal from to check permissions against). This approach is great, however I rapidly got tired of having to write out all of the code that this approach required, and I was getting annoyed with the clutter of try / finally blocks inside my tests (as well as forgetting to put the MockRepository into replay mode numerous times), so I stubbed out the principal and identity to create a much simpler alternative to the mocked versions. You can see these classes below:
public class PrincipalStub : IPrincipal
{
private readonly string _name;
private readonly string _authenticationType;
private readonly bool _isAuthenticated;
private readonly bool? _isInRoleResponse;
private readonly List<string> _roles;
public PrincipalStub( string name, string authenticationType, bool isAuthenticated, bool isInRoleResponse )
{
_name = name;
_isAuthenticated = isAuthenticated;
_authenticationType = authenticationType;
_isInRoleResponse = isInRoleResponse;
}
public PrincipalStub( string name, string authenticationType, bool isAuthenticated, params string[] roles )
{
_name = name;
_isAuthenticated = isAuthenticated;
_authenticationType = authenticationType;
_roles = new List<string>( roles );
}
public IIdentity Identity
{
get
{
return new IdentityStub( _name, _authenticationType, _isAuthenticated );
}
}
public bool IsInRole( string role )
{
if ( _isInRoleResponse.HasValue )
{
return _isInRoleResponse.Value;
}
return _roles.Contains( role );
}
}
public class IdentityStub : IIdentity
{
private readonly string _name;
private readonly string _authenticationType;
private readonly bool _isAuthenticated;
public IdentityStub( string name, string authenticationType, bool isAuthenticated )
{
_name = name;
_isAuthenticated = isAuthenticated;
_authenticationType = authenticationType;
}
public string Name
{
get
{
return _name;
}
}
public string AuthenticationType
{
get
{
return _authenticationType;
}
}
public bool IsAuthenticated
{
get
{
return _isAuthenticated;
}
}
}
This means I can now replace the mocks and all the associated setup with a single line of code:
IPrincipal testPrincipal = new PrincipalStub("Test", "Test", true, true);
which will create a new principal that is always in any role asked of it (remember we want to test the action, not the code access security). This still left me with the setup and teardown code that I could have put into appropriate methods in the test class, but that lacked the flexibility to specify the exact parameters of the PrincipalStub for each test, and meant that all of my tests would be running under a “false” principal – less than ideal.What I needed was a mechanism for performing a two-phase operation with a chunk of indeterminate code in the middle, and the guarantee that the second phase would always run. Delegates and anonymous methods could have worked, but I got my inspiration from an approach Oren Eini (Ayende) uses to provide a more explicit mocking syntax. Taking this and applying it to the scenario I had resulted in the following TestPrincipalManger:
public class TestPrincipalManager
{
private PrincipalStub _principal;
public TestPrincipalManager(string username, string authenticationType, bool isAuthenticated, params string[] roles)
{
_principal = new PrincipalStub(username, authenticationType, isAuthenticated, roles);
}
public TestPrincipalManager(string username, string authenticationType, bool isAuthenticated, bool isInRoleResponse)
{
_principal = new PrincipalStub(username, authenticationType, isAuthenticated, isInRoleResponse);
}
public IDisposable Attach()
{
IPrincipal originalPrincipal = Thread.CurrentPrincipal;
Thread.CurrentPrincipal = _principal;
return new TestPrincipalCleanup( originalPrincipal );
}
public class TestPrincipalCleanup : IDisposable
{
private readonly IPrincipal _principal;
public TestPrincipalCleanup( IPrincipal principal )
{
_principal = principal;
}
public void Dispose()
{
Thread.CurrentPrincipal = _principal;
GC.SuppressFinalize( this );
}
}
}
That can be used as follows:
[Test]
public void AdministratorPermissionAttribute_Permission_Succeeds_If_Principal_Does_Have_Administrator_Permission()
{
TestPrincipalManager authorisedPrincipal = new TestPrincipalManager("A.User", "Test Auth", true, "Administrator");
AdministratorPermissionAttribute permissionsAttribute = new AdministratorPermissionAttribute( SecurityAction.Demand );
IPermission permission = permissionsAttribute.CreatePermission();
using ( authorisedPrincipal.Attach() )
{
Assert.IsTrue(Thread.CurrentPrincipal.IsInRole("Administrator"), "Pre-condition failed: Current user does not have the Administrator permission");
permission.Demand();
}
}
While at first glance, this appears to be a perversion of the using syntax / IDisposable interface, if you take a second look it makes perfect sense. Using is essentially just a compiler macro that replaces the using with a try / finally, and the object that we are disposing of is following the semantics of the dispose operation – it is cleaning up after itself. Extracting the class doing the disposal out means that the Attach() method can be called repeatedly with no nasty side-effects (I hope!).