How can I check the ActionFilterAttributes that work with ModelState?
As suggested (among others) by Kazi Manzur Rashid in this blog post , I use ActionFilterAttributes
to transfer model state from one request to another when redirecting.
However, I cannot write a unit test that tests the behavior of these attributes. As an example, this is what I want to check for ImportModelStateAttribute
:
- Set
filterContext
toTempData[myKey]
contain some fake "exported" onesModelState
(ieModelStateDictionary
I create and add one bug myself) - Make
ModelState
contain one model error. - Challenge
OnActionExecuting
. - Make sure the two dictionaries are merged and
ModelState
now contains both errors.
I am at a loss at the very first step.
EDIT:
Yes, I tried mocking ActionFilterAttribute
with Moq, but I am getting errors stating
Invalid setting for a non-dependent member.
for TempData
and ModelState
.
source to share
Tomas, you don't need to mock the filterContext, you can create a real object to test the action filter, the same goes for the model state, these are poco objects. The only thing you need 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);
}
source to share