// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using Moq; using Xunit; using Assert = Microsoft.TestCommon.AssertEx; namespace System.Web.Mvc.Test { public class ValidatableObjectAdapterTest { // IValidatableObject support [Fact] public void NonIValidatableObjectInsideMetadataThrows() { // Arrange var context = new ControllerContext(); var validatable = new Mock(); var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => 42, typeof(IValidatableObject)); var validator = new ValidatableObjectAdapter(metadata, context); // Act & Assert Assert.Throws( () => validator.Validate(null), "The model object inside the metadata claimed to be compatible with System.ComponentModel.DataAnnotations.IValidatableObject, but was actually System.Int32."); } [Fact] public void IValidatableObjectGetsAProperlyPopulatedValidationContext() { // Arrange var context = new ControllerContext(); var validatable = new Mock(); var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => validatable.Object, validatable.Object.GetType()); var validator = new ValidatableObjectAdapter(metadata, context); ValidationContext validationContext = null; validatable.Setup(vo => vo.Validate(It.IsAny())) .Callback(vc => validationContext = vc) .Returns(Enumerable.Empty()) .Verifiable(); // Act validator.Validate(null); // Assert validatable.Verify(); Assert.Same(validatable.Object, validationContext.ObjectInstance); Assert.Null(validationContext.MemberName); } [Fact] public void IValidatableObjectWithNoErrors() { // Arrange var context = new ControllerContext(); var validatable = new Mock(); var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => validatable.Object, validatable.Object.GetType()); var validator = new ValidatableObjectAdapter(metadata, context); validatable.Setup(vo => vo.Validate(It.IsAny())) .Returns(Enumerable.Empty()); // Act IEnumerable results = validator.Validate(null); // Assert Assert.Empty(results); } [Fact] public void IValidatableObjectWithModelLevelError() { // Arrange var context = new ControllerContext(); var validatable = new Mock(); var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => validatable.Object, validatable.Object.GetType()); var validator = new ValidatableObjectAdapter(metadata, context); validatable.Setup(vo => vo.Validate(It.IsAny())) .Returns(new ValidationResult[] { new ValidationResult("Error Message") }); // Act ModelValidationResult result = validator.Validate(null).Single(); // Assert Assert.Equal("Error Message", result.Message); Assert.Equal(String.Empty, result.MemberName); } [Fact] public void IValidatableObjectWithMultipleModelLevelErrors() { // Arrange var context = new ControllerContext(); var validatable = new Mock(); var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => validatable.Object, validatable.Object.GetType()); var validator = new ValidatableObjectAdapter(metadata, context); validatable.Setup(vo => vo.Validate(It.IsAny())) .Returns(new ValidationResult[] { new ValidationResult("Error Message 1"), new ValidationResult("Error Message 2") }); // Act ModelValidationResult[] results = validator.Validate(null).ToArray(); // Assert Assert.Equal(2, results.Length); Assert.Equal("Error Message 1", results[0].Message); Assert.Equal("Error Message 2", results[1].Message); } [Fact] public void IValidatableObjectWithMultiPropertyValidationFailure() { // Arrange var context = new ControllerContext(); var validatable = new Mock(); var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => validatable.Object, validatable.Object.GetType()); var validator = new ValidatableObjectAdapter(metadata, context); validatable.Setup(vo => vo.Validate(It.IsAny())) .Returns(new[] { new ValidationResult("Error Message", new[] { "Property1", "Property2" }) }) .Verifiable(); // Act ModelValidationResult[] results = validator.Validate(null).ToArray(); // Assert validatable.Verify(); Assert.Equal(2, results.Length); Assert.Equal("Error Message", results[0].Message); Assert.Equal("Property1", results[0].MemberName); Assert.Equal("Error Message", results[1].Message); Assert.Equal("Property2", results[1].MemberName); } [Fact] public void IValidatableObjectWhichIsNullReturnsNoErrors() { // Arrange var context = new ControllerContext(); var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => null, typeof(IValidatableObject)); var validator = new ValidatableObjectAdapter(metadata, context); // Act IEnumerable results = validator.Validate(null); // Assert Assert.Empty(results); } [Fact] public void IValidatableObjectWhichReturnsValidationResultSuccessReturnsNoErrors() { // Arrange var context = new ControllerContext(); var validatable = new Mock(); var metadata = ModelMetadataProviders.Current.GetMetadataForType(() => validatable.Object, validatable.Object.GetType()); var validator = new ValidatableObjectAdapter(metadata, context); validatable.Setup(vo => vo.Validate(It.IsAny())) .Returns(new[] { ValidationResult.Success }) .Verifiable(); // Act ModelValidationResult[] results = validator.Validate(null).ToArray(); // Assert validatable.Verify(); Assert.Empty(results); } } }