Reputation: 883
I have a validator set up that needs to use values outside of the viewmodel being validated. So to do this I use the ValidationContext and assign RootContextData and then call validate method within the controller, if it returns an error I add it to the modelstate. This all works fine but I can't work out how to test it, or maybe this is flagging that I haven't done it in the best way.
E.g. the validator:
RuleFor(x => x.StartDate.Date.Day)
.Custom((day, context) =>
{
if (!context.RootContextData.TryGetValue("TargetDate", out var targetDate)) return;
var dateVm = context.InstanceToValidate;
if (DatesHelper.SourceDateStringIsGreaterThanTargetDateString(
dateVm.StartDate.DateInputAsString(),
targetDate as string) == true)
{
context.AddFailure("The Start date must be on or before the target date for the action");
}
});
And then in the controller..
. . .
var repositoryResult = customerRepo.Result;
if (!ModelState.IsValid)
{
return View(vm);
}
var validationContext = new ValidationContext<StartDateViewModel>(vm)
{
RootContextData =
{
["TargetDate"] = repositoryResult.Dates.Target
}
};
var validator = new StartDateValidator();
var validationResult = await validator.ValidateAsync(validationContext);
if (!validationResult.IsValid)
{
ModelState.AddModelError("StartDate.Date.Day", validationResult.Errors.First().ErrorMessage);
return View(vm);
}
. . .
Obviously I could just pass in a view model with the incorrect dates which will flag this but then it feels like I'm testing the validator within the controller.. What I really want to do (i think) is to pass a viewmodel with arbitrary dates, get the validator to fail on that rule and then assert that the error has been added to modelstate. Any help is appreciated.
Upvotes: 0
Views: 1527
Reputation: 21
I think what you can do is Test the Controller logic. An example might be something like this:
[Test]
public void IndexPost_AddModelStateError_WhenInvalidData()
{
var controller = new HomeController();
var vm = ... //Test Data
var result = controller.Index(vm) as ViewResult;
Assert.IsTrue(result.ViewData.ModelState["StartDate.Date.Day"].Errors.Any());
}
Here you can find the Microsoft documentation about testing the controller logic
Upvotes: 1