222 lines
8.8 KiB
C#
222 lines
8.8 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel.DataAnnotations;
|
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
|
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
|
using Xunit;
|
|
|
|
namespace Microsoft.AspNetCore.Mvc.DataAnnotations.Internal
|
|
{
|
|
public class ValidatableObjectAdapterTest
|
|
{
|
|
private static readonly ModelMetadataProvider _metadataProvider
|
|
= TestModelMetadataProvider.CreateDefaultProvider();
|
|
|
|
// Inspired by DataAnnotationsModelValidatorTest.Validate_SetsMemberName_AsExpectedData but using a type that
|
|
// implements IValidatableObject. Values are metadata, expected DisplayName, and expected MemberName.
|
|
public static TheoryData<ModelMetadata, string, string> Validate_PassesExpectedNamesData
|
|
{
|
|
get
|
|
{
|
|
var method = typeof(SampleModel).GetMethod(nameof(SampleModel.IsLovely));
|
|
var parameter = method.GetParameters()[0]; // IsLovely(SampleModel other)
|
|
return new TheoryData<ModelMetadata, string, string>
|
|
{
|
|
{
|
|
// Validating a property.
|
|
_metadataProvider.GetMetadataForProperty(
|
|
typeof(SampleModelContainer),
|
|
nameof(SampleModelContainer.SampleModel)),
|
|
nameof(SampleModelContainer.SampleModel),
|
|
nameof(SampleModelContainer.SampleModel)
|
|
},
|
|
{
|
|
// Validating a property with [Display(Name = "...")].
|
|
_metadataProvider.GetMetadataForProperty(
|
|
typeof(SampleModelContainer),
|
|
nameof(SampleModelContainer.SampleModelWithDisplay)),
|
|
"sample model",
|
|
nameof(SampleModelContainer.SampleModelWithDisplay)
|
|
},
|
|
{
|
|
// Validating a parameter.
|
|
_metadataProvider.GetMetadataForParameter(parameter),
|
|
"other",
|
|
"other"
|
|
},
|
|
{
|
|
// Validating a top-level parameter when using old-fashioned metadata provider.
|
|
// Or, validating an element of a collection.
|
|
_metadataProvider.GetMetadataForType(typeof(SampleModel)),
|
|
nameof(SampleModel),
|
|
null
|
|
},
|
|
};
|
|
}
|
|
}
|
|
|
|
public static TheoryData<ValidationResult[], ModelValidationResult[]> Validate_ReturnsExpectedResultsData
|
|
{
|
|
get
|
|
{
|
|
return new TheoryData<ValidationResult[], ModelValidationResult[]>
|
|
{
|
|
{
|
|
new[] { new ValidationResult("Error message") },
|
|
new[] { new ModelValidationResult(memberName: null, message: "Error message") }
|
|
},
|
|
{
|
|
new[] { new ValidationResult("Error message", new[] { nameof(SampleModel.FirstName) }) },
|
|
new[] { new ModelValidationResult(nameof(SampleModel.FirstName), "Error message") }
|
|
},
|
|
{
|
|
new[]
|
|
{
|
|
new ValidationResult("Error message1"),
|
|
new ValidationResult("Error message2", new[] { nameof(SampleModel.FirstName) }),
|
|
new ValidationResult("Error message3", new[] { nameof(SampleModel.LastName) }),
|
|
new ValidationResult("Error message4", new[] { nameof(SampleModel) }),
|
|
},
|
|
new[]
|
|
{
|
|
new ModelValidationResult(memberName: null, message: "Error message1"),
|
|
new ModelValidationResult(nameof(SampleModel.FirstName), "Error message2"),
|
|
new ModelValidationResult(nameof(SampleModel.LastName), "Error message3"),
|
|
// No special case for ValidationContext.MemberName==ValidationResult.MemberName
|
|
new ModelValidationResult(nameof(SampleModel), "Error message4"),
|
|
}
|
|
},
|
|
{
|
|
new[]
|
|
{
|
|
new ValidationResult("Error message1", new[]
|
|
{
|
|
nameof(SampleModel.FirstName),
|
|
nameof(SampleModel.LastName),
|
|
}),
|
|
new ValidationResult("Error message2"),
|
|
},
|
|
new[]
|
|
{
|
|
new ModelValidationResult(nameof(SampleModel.FirstName), "Error message1"),
|
|
new ModelValidationResult(nameof(SampleModel.LastName), "Error message1"),
|
|
new ModelValidationResult(memberName: null, message: "Error message2"),
|
|
}
|
|
},
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
[Theory]
|
|
[MemberData(nameof(Validate_PassesExpectedNamesData))]
|
|
public void Validate_PassesExpectedNames(
|
|
ModelMetadata metadata,
|
|
string expectedDisplayName,
|
|
string expectedMemberName)
|
|
{
|
|
// Arrange
|
|
var adapter = new ValidatableObjectAdapter();
|
|
var model = new SampleModel();
|
|
var validationContext = new ModelValidationContext(
|
|
new ActionContext(),
|
|
metadata,
|
|
_metadataProvider,
|
|
container: new SampleModelContainer(),
|
|
model: model);
|
|
|
|
// Act
|
|
var results = adapter.Validate(validationContext);
|
|
|
|
// Assert
|
|
Assert.NotNull(results);
|
|
Assert.Empty(results);
|
|
|
|
Assert.Equal(expectedDisplayName, model.DisplayName);
|
|
Assert.Equal(expectedMemberName, model.MemberName);
|
|
Assert.Equal(model, model.ObjectInstance);
|
|
}
|
|
|
|
[Theory]
|
|
[MemberData(nameof(Validate_ReturnsExpectedResultsData))]
|
|
public void Validate_ReturnsExpectedResults(
|
|
ValidationResult[] innerResults,
|
|
ModelValidationResult[] expectedResults)
|
|
{
|
|
// Arrange
|
|
var adapter = new ValidatableObjectAdapter();
|
|
var model = new SampleModel();
|
|
foreach (var result in innerResults)
|
|
{
|
|
model.ValidationResults.Add(result);
|
|
}
|
|
|
|
var metadata = _metadataProvider.GetMetadataForProperty(
|
|
typeof(SampleModelContainer),
|
|
nameof(SampleModelContainer.SampleModel));
|
|
var validationContext = new ModelValidationContext(
|
|
new ActionContext(),
|
|
metadata,
|
|
_metadataProvider,
|
|
container: null,
|
|
model: model);
|
|
|
|
// Act
|
|
var results = adapter.Validate(validationContext);
|
|
|
|
// Assert
|
|
Assert.NotNull(results);
|
|
Assert.Equal(expectedResults, results, ModelValidationResultComparer.Instance);
|
|
}
|
|
|
|
private class SampleModel : IValidatableObject
|
|
{
|
|
// "Real" properties.
|
|
|
|
public string FirstName { get; set; }
|
|
|
|
public string LastName { get; set; }
|
|
|
|
// ValidationContext members passed to Validate(...)
|
|
|
|
public string DisplayName { get; private set; }
|
|
|
|
public string MemberName { get; private set; }
|
|
|
|
public object ObjectInstance { get; private set; }
|
|
|
|
// What Validate(...) should return.
|
|
|
|
public IList<ValidationResult> ValidationResults { get; } = new List<ValidationResult>();
|
|
|
|
// Test method.
|
|
|
|
public bool IsLovely(SampleModel other)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// IValidatableObject for realz.
|
|
|
|
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
|
{
|
|
DisplayName = validationContext.DisplayName;
|
|
MemberName = validationContext.MemberName;
|
|
ObjectInstance = validationContext.ObjectInstance;
|
|
|
|
return ValidationResults;
|
|
}
|
|
}
|
|
|
|
private class SampleModelContainer
|
|
{
|
|
[Display(Name = "sample model")]
|
|
public SampleModel SampleModelWithDisplay { get; set; }
|
|
|
|
public SampleModel SampleModel { get; set; }
|
|
}
|
|
}
|
|
}
|