To answer your 2nd question first, no, AOP doesn’t inherently conflict with unit testing. Usually I’d say it’s best to unit test the methods and the aspects separately.
In your case, there are several options.
The easiest is simply to have the unit test setup method make sure the thread has the required permissions.
If you don’t want to do that, there are two ways you could separate things out for your unit test.
The first is to extract all the code from the methods that you are applying security aspects to into separate methods like this:
[SecurityAspect]
void DoSomething()
{
DoSomethingInternal();
}
void DoSomethingInternal()
{
// this is the real code
}
Then you can run your unit tests against all the unsecured ‘internal’ methods – which tests the logic in them without worrying about security.
The second approach would be to inject a mock permissions tester into the aspect itself. To be able to do this, you would have to define a separate class and interface that does the actual logic of testing the security, something like this (assuming it’s a Thread that you pass in to verify the security):
public interface IPermissionsChecker
{
bool HasPermissions(Thread thread);
}
This is your permissions checker for your live system:
public class RealPermissionsChecker : IPermissionsChecker
{
public bool HasPermissions(Thread thread)
{
// do your real work here
}
}
And this is the one you’ll use in your unit tests
public class MockPermissionsChecker : IPermissionsChecker
{
public bool HasPermissions(Thread thread)
{
return true;
}
}
Now you need to define your aspect something like this:
public class SecurityChecker : OnMethodBoundaryAspect
{
IPermissionsChecker _checker;
public override void OnEntry(MethodExecutionArgs args)
{
if (!_checker.HasPermissions(Thread.CurrentThread))
throw new SecurityException("No permissions");
}
}
The only remaining issue is the need to inject the correct permissions checker into the aspect.
The slightly hacky way I've done this before is to make _checker a static field, and provide a static method to initialize it:
public class SecurityChecker : OnMethodBoundaryAspect
{
private static IPermissionsChecker _checker;
public static void InjectChecker(IPermissionsChecker checker)
{
// best put some code here to make sure this is only called once,
// as well as doing thread synchronization
if (_checker == null)
_checker = checker;
}
The fact that InjectChecker is static means you can access it from your app startup (or unit test startup) code. I suspect unit test purists would frown on this - and you do have to make sure you do call it at app startup, but I think it is the simplest way to inject the checker into the aspect, circumventing the fact that the rest of your code can't directly access instances of the aspect.
The more complicated alternative is to override RunTimeInitialize() in your aspect - this method is called by PostSharp when the aspect is initialized. You'd probably do something like this:
public override void RuntimeInitialize(MethodBase method)
{
base.RuntimeInitialize();
this._checker =PermissionsCheckerProvider.Current.GetChecker();
}
You'll see that requires you to define another class:
public class PermissionsCheckerProvider
{
// make sure you set this at app startup, either to the mock or to the real checker
public static PermissionsCheckerProvider Current { get; set;}
public IPermissionsChecker GetChecker()
{
}
}
This approach guarantees that the method will attempt its initialization at the right time, but then you have the problem of making sure you have supplied an appropriate current provider before the aspect attempts to initialize. So I personally would probably go for the first approach to keep things simple.
There's some discussion about dependency injection and RuntimeInitialize here. https://codereview.stackexchange.com/questions/20341/inject-dependency-into-postsharp-aspect