In a custom ActionFilter
, I want check the attributes on the controller action that will be executed. Running through a small test application, the following works when launching the app in the asp.net development server-
public class CustomActionFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var someAttribute = filterContext.ActionDescriptor
.GetCustomAttributes(typeof(SomeAttribute), false)
.Cast<SomeAttribute>()
.SingleOrDefault();
if (someAttribute == null)
{
throw new ArgumentException();
}
// do something here
}
public override void OnActionExecuted(ActionExecutingContext filterContext)
{
// ...
}
}
An action method without SomeAttribute
throws an ArgumentException
and conversely, an action method with SomeAttribute
does not. So far so good.
Now I would like to set up some unit tests for the ActionFilter, but how can I set up the action method upon which the OnActionExecuting
method should run in the unit test? Using the following code doesn't find SomeAttribute
on the action method which will be executed. Is the test set up correctly? Have I not arranged something correctly in the test? To clarify, the test is not complete but I'm not sure what I've missed such that someAttribute
in OnActionExecuting
in the test is null
[TestMethod]
public void Controller_With_SomeAttribute()
{
FakeController fakeController =
new FakeController();
ControllerContext controllerContext =
new ControllerContext(new Mock<HttpContextBase>().Object,
new RouteData(),
fakeController);
var actionDescriptor = new Mock<ActionDescriptor>();
actionDescriptor.SetupGet(x => x.ActionName).Returns("Action_With_SomeAttribute");
ActionExecutingContext actionExecutingContext =
new ActionExecutingContext(controllerContext,
actionDescriptor.Object,
new RouteValueDictionary());
CustomActionFilterAttribute customActionFilterAttribute = new CustomActionFilterAttribute ();
customActionFilterAttribute.OnActionExecuting(actionExecutingContext);
}
private class FakeController : Controller
{
[SomeAttribute]
ActionResult Action_With_SomeAttribute()
{
return View();
}
}
Since the ActionDescriptor property of ActionExecutingContext
is virtual, you can just override
that and provide your own implementation of ActionDescriptor
.
Here are two tests that verify the two branches through the current implementation of OnActionExecuting
:
[ExpectedException(typeof(ArgumentException))]
[TestMethod]
public void OnActionExecutingWillThrowWhenSomeAttributeIsNotPresent()
{
// Fixture setup
var ctxStub = new Mock<ActionExecutingContext>();
ctxStub.Setup(ctx => ctx.ActionDescriptor.GetCustomAttributes(typeof(SomeAttribute), false))
.Returns(new object[0]);
var sut = new CustomActionFilterAttribute();
// Exercise system
sut.OnActionExecuting(ctxStub.Object);
// Verify outcome (expected exception)
// Teardown
}
[TestMethod]
public void OnActionExecutingWillNotThrowWhenSomeAttributeIsPresent()
{
// Fixture setup
var ctxStub = new Mock<ActionExecutingContext>();
ctxStub.Setup(ctx => ctx.ActionDescriptor.GetCustomAttributes(typeof(SomeAttribute), false))
.Returns(new object[] { new SomeAttribute() });
var sut = new CustomActionFilterAttribute();
// Exercise system
sut.OnActionExecuting(ctxStub.Object);
// Verify outcome (no exception indicates success)
// Teardown
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With