ActionFilter Unit Testing - Configuring ActionExecutingContext Properly

In a custom ActionFilter , I want to check the attributes of the controller action that will be executed. When you run a small test application, when you run the application on the asp.net development server, the following occurs:

 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 a ArgumentException and, conversely, an action method with SomeAttribute does not. So far, so good.

Now I would like to configure some unit tests for ActionFilter, but how can I configure the action method by which the OnActionExecuting method should be run in the unit test? Using the following code does not find SomeAttribute in the action method that will be executed. Is the test installed correctly? Didn't I do something right in the test? To clarify, the test is not completed, but I'm not sure what I missed, so 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(); } } 
+4
source share
1 answer

Since the ActionDescriptor property for the ActionExecutingContext is virtual, you can simply override and provide your own implementation of the ActionDescriptor .

Here are two tests that test two branches through the current OnActionExecuting implementation:

 [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 } 
+5
source

Source: https://habr.com/ru/post/1302925/


All Articles