开发者

How do I test ActionFilterAttributes that work with ModelState?

As suggested by (among others) Kazi Manzur Rashid in this blog post, I am using ActionFilterAttributes to transfer model state from one request to another when redirecting.

However, I find myself unable to write a unit test that test the behavior of these attributes. As an example, this what I want the test for the ImportModelStateAttribute to do:

  1. Setup the filterContext so that TempData[myKey] contains some fake "exported" ModelState (that is, a ModelStateDictionary I create myself, and add one error to)
  2. Make ModelState contain one model error.
  3. Call OnActionExecuting.
  4. Verify the two dictionaries are merged, and ModelState now contai开发者_如何学Gons both errors.

I'm at a loss already on the first step.

EDIT:

Yes, I've tried mocking ActionFilterAttribute with Moq, but I get errors stating

Invalid setup on non-overridable member

for both TempData and ModelState.


Tomas, You do not have to mock the filterContext, you can create the real object for testing the action filter, the same goes for the model state, these are poco objects. Only thing that you have to mock is the HttpContext (if needed).

[Fact]
public void Should_import_complete_view_data()
{
    var attribute = new ImportViewDataFromTempDataAttribute();

    var httpContext = new Mock<HttpContextBase>();
    var requestContext = new RequestContext(httpContext.Object, new RouteData());

    var previousModel = new object();
    var previousViewData = new ViewDataDictionary(previousModel) {{"foo", "bar"}};

    previousViewData.ModelState.AddModelError("foo", "bar");

    var controller = new Mock<ControllerBase>();
    controller.Object.ViewData = new ViewDataDictionary();
    controller.Object.TempData = new TempDataDictionary { { attribute.Key, previousViewData } };

    var controllerContext = new ControllerContext(requestContext, controller.Object);
    var actionContext = new ActionExecutingContext(controllerContext, new Mock<ActionDescriptor>().Object, new Dictionary<string, object>());

    attribute.OnActionExecuting(actionContext);

    Assert.True(actionContext.Controller.ViewData.ContainsKey("foo"));
    Assert.True(actionContext.Controller.ViewData.ModelState.ContainsKey("foo"));
    Assert.Same(previousModel, actionContext.Controller.ViewData.Model);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜