Adds test for proposal in #7014

This commit is contained in:
Jeremy Skinner 2017-11-21 20:45:13 +00:00 committed by Ryan Nowak
parent 3a132e4af5
commit 711a618310
1 changed files with 105 additions and 0 deletions

View File

@ -3,8 +3,11 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
@ -132,6 +135,76 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
AssertErrorEquals(contactUsMax + contactusRegEx, modelStateErrors["[1].Contact"]);
}
[Fact]
public void ValidationVisitor_ValidateComplexTypesIfChildValidationFailsSetToTrue_AddsModelLevelErrors()
{
// Arrange
var testContext = ModelBindingTestHelper.GetTestContext();
var modelState = testContext.ModelState;
var model = new ModelLevelErrorTest();
var controller = CreateController(testContext, testContext.MetadataProvider);
controller.ObjectValidator = new CustomObjectValidator(testContext.MetadataProvider, TestModelValidatorProvider.CreateDefaultProvider().ValidatorProviders)
{
ValidateComplexTypesIfChildValidationFails = true
};
// Act
var result = controller.TryValidateModel(model);
// Assert
Assert.False(result);
Assert.False(modelState.IsValid);
var modelStateErrors = GetModelStateErrors(modelState);
Assert.Equal(2, modelStateErrors.Count);
AssertErrorEquals("Property", modelStateErrors["Message"]);
AssertErrorEquals("Model", modelStateErrors[""]);
}
[Fact]
public void ValidationVisitor_ValidateComplexTypesIfChildValidationFailsSetToFalse_DoesNotAddModelLevelErrors()
{
// Arrange
var testContext = ModelBindingTestHelper.GetTestContext();
var modelState = testContext.ModelState;
var model = new ModelLevelErrorTest();
var controller = CreateController(testContext, testContext.MetadataProvider);
controller.ObjectValidator = new CustomObjectValidator(testContext.MetadataProvider, TestModelValidatorProvider.CreateDefaultProvider().ValidatorProviders)
{
ValidateComplexTypesIfChildValidationFails= false
};
// Act
var result = controller.TryValidateModel(model);
// Assert
Assert.False(result);
Assert.False(modelState.IsValid);
var modelStateErrors = GetModelStateErrors(modelState);
Assert.Single(modelStateErrors); // single error from the required attribute
AssertErrorEquals("Property", modelStateErrors.Single().Value);
}
[ModelLevelError]
private class ModelLevelErrorTest
{
[Required(ErrorMessage = "Property")]
public string Message { get; set; }
}
private class ModelLevelErrorAttribute : ValidationAttribute
{
public ModelLevelErrorAttribute()
{
ErrorMessage = "Model";
}
public override bool IsValid(object value)
{
return false;
}
}
private void AssertErrorEquals(string expected, string actual)
{
// OrderBy is used because the order of the results may very depending on the platform / client.
@ -179,5 +252,37 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
private class TestController : Controller
{
}
private class CustomObjectValidator : IObjectModelValidator
{
private readonly IModelMetadataProvider _modelMetadataProvider;
private readonly IList<IModelValidatorProvider> _validatorProviders;
private ValidatorCache _validatorCache;
private CompositeModelValidatorProvider _validatorProvider;
public CustomObjectValidator(IModelMetadataProvider modelMetadataProvider, IList<IModelValidatorProvider> validatorProviders)
{
_modelMetadataProvider = modelMetadataProvider;
_validatorProviders = validatorProviders;
_validatorCache = new ValidatorCache();
_validatorProvider = new CompositeModelValidatorProvider(validatorProviders);
}
public void Validate(ActionContext actionContext, ValidationStateDictionary validationState, string prefix, object model)
{
var visitor = new ValidationVisitor(
actionContext,
_validatorProvider,
_validatorCache,
_modelMetadataProvider,
validationState);
var metadata = model == null ? null : _modelMetadataProvider.GetMetadataForType(model.GetType());
visitor.ValidateComplexTypesIfChildValidationFails = ValidateComplexTypesIfChildValidationFails;
visitor.Validate(metadata, prefix, model);
}
public bool ValidateComplexTypesIfChildValidationFails { get; set; }
}
}
}