Weaving with xUnit.net
There has been mixed reaction to the removal of [SetUp]
and [TearDown]
in xUnit.net. Personally, I think it's great as it helps to raise unit test 'smells', particularly around how classes interact with each another. Here's a small example of how we can use the BeforeAfterTestAttribute
in xUnit to remove duplicate code. (It's based on the security workaround I talked about yesterday.)
Instead of repeating three lines of code in each unit test to update the current identity, we can just define an attribute like [AssumeIdentity]
that will take care of things for us. Here's the little fixture I wrote to test it.
public class AssumeIdentityAttributeFixture
{
[Test]
public void CallingSecuredMethodWillThrow()
{
Assert.Throws<SecurityException>(delegate
{
SecuredMethod();
});
}
[Test, AssumeIdentity("Munchkin")]
public void CallingSecuredMethodWithAssumedIdentityPasses()
{
Assert.DoesNotThrow(delegate
{
SecuredMethod();
});
}
[PrincipalPermission(SecurityAction.Demand, Role = "Munchkin")]
public void SecuredMethod() {}
}
public class AssumeIdentityAttribute : BeforeAfterTestAttribute
{
public AssumeIdentityAttribute(string name)
{
this.name = name;
}
public override void Before(MethodInfo methodUnderTest)
{
originalPrincipal = Thread.CurrentPrincipal;
GenericIdentity identity = new GenericIdentity("boo");
GenericPrincipal principal =
new GenericPrincipal(identity, new string[] { name });
Thread.CurrentPrincipal = principal;
}
public override void After(MethodInfo methodUnderTest)
{
Thread.CurrentPrincipal = originalPrincipal;
}
readonly string name;
IPrincipal originalPrincipal;
}
As you can see, before each test it executed, we update the current thread's identity, and then reset it after the test has run. It doesn't get much simpler than that :)