public void AddValidation_DoesNotTrounceExistingAttributes() { // Arrange var attribute = new RemoteAttribute("Action", "Controller", "AnotherArea") { HttpMethod = "PUT", }; var context = GetValidationContextWithArea(currentArea: "Test"); context.Attributes.Add("data-val", "original"); context.Attributes.Add("data-val-remote", "original"); context.Attributes.Add("data-val-remote-additionalfields", "original"); context.Attributes.Add("data-val-remote-type", "original"); context.Attributes.Add("data-val-remote-url", "original"); // Act attribute.AddValidation(context); // Assert Assert.Collection( context.Attributes, kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("original", kvp.Value); }, kvp => { Assert.Equal("data-val-remote", kvp.Key); Assert.Equal("original", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-additionalfields", kvp.Key); Assert.Equal("original", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-type", kvp.Key); Assert.Equal("original", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-url", kvp.Key); Assert.Equal("original", kvp.Value); }); }
public void AddValidation_WithActionControllerArea_CallsUrlHelperWithExpectedValues() { // Arrange var attribute = new RemoteAttribute("Action", "Controller", "Test") { HttpMethod = "POST", }; var url = "/Test/Controller/Action"; var urlHelper = new MockUrlHelper(url, routeName: null); var context = GetValidationContext(urlHelper); // Act attribute.AddValidation(context); // Assert Assert.Collection( context.Attributes, kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); }, kvp => { Assert.Equal("data-val-remote", kvp.Key); Assert.Equal("'Length' is invalid.", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-additionalfields", kvp.Key); Assert.Equal("*.Length", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-type", kvp.Key); Assert.Equal("POST", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-url", kvp.Key); Assert.Equal(url, kvp.Value); }); var routeDictionary = Assert.IsType <RouteValueDictionary>(urlHelper.RouteValues); Assert.Equal(3, routeDictionary.Count); Assert.Equal("Action", routeDictionary["action"] as string); Assert.Equal("Controller", routeDictionary["controller"] as string); Assert.Equal("Test", routeDictionary["area"] as string); }
public void AddValidation_WithErrorMessageAndLocalizerFactory_SetsAttributesAsExpected() { // Arrange var expected = "Error about 'Length' from override."; var attribute = new RemoteAttribute("Action", "Controller") { HttpMethod = "POST", ErrorMessage = "Error about '{0}' from override.", }; var url = "/Controller/Action"; var context = GetValidationContextWithLocalizerFactory(url); // Act attribute.AddValidation(context); // Assert Assert.Collection( context.Attributes, kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); }, kvp => { // IStringLocalizerFactory existence alone is insufficient to change error message. Assert.Equal("data-val-remote", kvp.Key); Assert.Equal(expected, kvp.Value); }, kvp => { Assert.Equal("data-val-remote-additionalfields", kvp.Key); Assert.Equal("*.Length", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-type", kvp.Key); Assert.Equal("POST", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-url", kvp.Key); Assert.Equal(url, kvp.Value); }); }
public void ErrorMessageProperties_HaveExpectedDefaultValues() { // Arrange & Act var attribute = new RemoteAttribute("Action", "Controller"); // Assert Assert.Null(attribute.ErrorMessage); Assert.Null(attribute.ErrorMessageResourceName); Assert.Null(attribute.ErrorMessageResourceType); }
public void FormatPropertyForClientValidation_WithInvalidPropertyName_Throws(string property) { // Arrange var expected = "Value cannot be null or empty."; // Act & Assert ExceptionAssert.ThrowsArgument( () => RemoteAttribute.FormatPropertyForClientValidation(property), "property", expected); }
public void AddValidation_WithBadRouteName_Throws() { // Arrange var attribute = new RemoteAttribute("nonexistentRoute"); var context = GetValidationContextWithArea(currentArea: null); // Act & Assert var exception = Assert.Throws <InvalidOperationException>(() => attribute.AddValidation(context)); Assert.Equal("No URL for remote validation could be found.", exception.Message); }
public void FormatPropertyForClientValidation_WithInvalidPropertyName_Throws(string property) { // Arrange var expected = "Value cannot be null or empty." + Environment.NewLine + "Parameter name: property"; // Act & Assert var exception = Assert.Throws <ArgumentException>( "property", () => RemoteAttribute.FormatPropertyForClientValidation(property)); Assert.Equal(expected, exception.Message); }
public void FormatAdditionalFieldsForClientValidation_WithInvalidPropertyName_Throws(string property) { // Arrange var attribute = new RemoteAttribute(routeName: "default"); var expectedMessage = "Value cannot be null or empty."; // Act & Assert ExceptionAssert.ThrowsArgument( () => attribute.FormatAdditionalFieldsForClientValidation(property), "property", expectedMessage); }
public void AddValidation_WithErrorMessageLocalizerFactoryLocalizerProviderAndDisplayName_SetsAttributesAsExpected() { // Arrange var expected = "Error about 'Length' from localizer."; var attribute = new RemoteAttribute("Action", "Controller") { HttpMethod = "POST", ErrorMessage = "Error about '{0}' from override.", }; var url = "/Controller/Action"; var metadataProvider = new TestModelMetadataProvider(); metadataProvider .ForProperty(typeof(string), nameof(string.Length)) .DisplayDetails(d => d.DisplayName = () => "Display Length"); var context = GetValidationContextWithLocalizerFactory(url, metadataProvider); var localizedString = new LocalizedString("Fred", expected); var localizer = new Mock <IStringLocalizer>(MockBehavior.Strict); localizer .Setup(l => l["Error about '{0}' from override.", "Display Length"]) .Returns(localizedString) .Verifiable(); var options = context.ActionContext.HttpContext.RequestServices .GetRequiredService <IOptions <MvcDataAnnotationsLocalizationOptions> >(); options.Value.DataAnnotationLocalizerProvider = (type, factory) => localizer.Object; // Act attribute.AddValidation(context); // Assert localizer.VerifyAll(); Assert.Collection( context.Attributes, kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); }, kvp => { Assert.Equal("data-val-remote", kvp.Key); Assert.Equal(expected, kvp.Value); }, kvp => { Assert.Equal("data-val-remote-additionalfields", kvp.Key); Assert.Equal("*.Length", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-type", kvp.Key); Assert.Equal("POST", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-url", kvp.Key); Assert.Equal(url, kvp.Value); }); }
public void FormatErrorMessage_ReturnsDefaultErrorMessage() { // Arrange // See ViewFeatures.Resources.RemoteAttribute_RemoteValidationFailed. var expected = "'Property1' is invalid."; var attribute = new RemoteAttribute("Action", "Controller"); // Act var message = attribute.FormatErrorMessage("Property1"); // Assert Assert.Equal(expected, message); }
public void FormatErrorMessage_UsesOverriddenErrorMessage() { // Arrange var expected = "Error about 'Property1' from override."; var attribute = new RemoteAttribute("Action", "Controller") { ErrorMessage = "Error about '{0}' from override.", }; // Act var message = attribute.FormatErrorMessage("Property1"); // Assert Assert.Equal(expected, message); }
public void FormatErrorMessage_UsesErrorMessageFromResource() { // Arrange var expected = "Error about 'Property1' from resources."; var attribute = new RemoteAttribute("Action", "Controller") { ErrorMessageResourceName = nameof(Resources.RemoteAttribute_Error), ErrorMessageResourceType = typeof(Resources), }; // Act var message = attribute.FormatErrorMessage("Property1"); // Assert Assert.Equal(expected, message); }
public void AddValidation_WithActionControllerAreaInArea_FindsControllerInDifferentArea() { // Arrange var attribute = new RemoteAttribute("Action", "Controller", "AnotherArea"); var context = GetValidationContextWithArea(currentArea: "Test"); // Act attribute.AddValidation(context); // Assert Assert.Collection( context.Attributes, kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); }, kvp => { Assert.Equal("data-val-remote", kvp.Key); Assert.Equal("'Length' is invalid.", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-additionalfields", kvp.Key); Assert.Equal("*.Length", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-url", kvp.Key); Assert.Equal("/AnotherArea/Controller/Action", kvp.Value); }); }
public void AddValidation_WithActionControllerArea_FindsControllerInNamedArea() { // Arrange var attribute = new RemoteAttribute("Action", "Controller", "Test"); var context = GetValidationContextWithArea(currentArea: null); // Act attribute.AddValidation(context); // Assert Assert.Collection( context.Attributes, kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); }, kvp => { Assert.Equal("data-val-remote", kvp.Key); Assert.Equal("'Length' is invalid.", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-additionalfields", kvp.Key); Assert.Equal("*.Length", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-url", kvp.Key); Assert.Equal("/UrlEncode[[Test]]/UrlEncode[[Controller]]/UrlEncode[[Action]]", kvp.Value); }); }
public void AddValidation_WithErrorResourcesLocalizerFactoryAndLocalizerProvider_SetsAttributesAsExpected() { // Arrange var expected = "Error about 'Length' from resources."; var attribute = new RemoteAttribute("Action", "Controller") { HttpMethod = "POST", ErrorMessageResourceName = nameof(Resources.RemoteAttribute_Error), ErrorMessageResourceType = typeof(Resources), }; var url = "/Controller/Action"; var context = GetValidationContextWithLocalizerFactory(url); var localizer = new Mock <IStringLocalizer>(MockBehavior.Strict); var options = context.ActionContext.HttpContext.RequestServices .GetRequiredService <IOptions <MvcDataAnnotationsLocalizationOptions> >(); options.Value.DataAnnotationLocalizerProvider = (type, factory) => localizer.Object; // Act attribute.AddValidation(context); // Assert Assert.Collection( context.Attributes, kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); }, kvp => { // Configuring the attribute using ErrorMessageResource* trumps available IStringLocalizer etc. Assert.Equal("data-val-remote", kvp.Key); Assert.Equal(expected, kvp.Value); }, kvp => { Assert.Equal("data-val-remote-additionalfields", kvp.Key); Assert.Equal("*.Length", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-type", kvp.Key); Assert.Equal("POST", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-url", kvp.Key); Assert.Equal(url, kvp.Value); }); }
public void AddValidation_WithErrorMessageAndLocalizerProvider_SetsAttributesAsExpected() { // Arrange var expected = "Error about 'Length' from override."; var attribute = new RemoteAttribute("Action", "Controller") { HttpMethod = "POST", ErrorMessage = "Error about '{0}' from override.", }; var url = "/Controller/Action"; var context = GetValidationContext(url); var options = context.ActionContext.HttpContext.RequestServices .GetRequiredService <IOptions <MvcDataAnnotationsLocalizationOptions> >(); var localizer = new Mock <IStringLocalizer>(MockBehavior.Strict); options.Value.DataAnnotationLocalizerProvider = (type, factory) => localizer.Object; // Act attribute.AddValidation(context); // Assert Assert.Collection( context.Attributes, kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); }, kvp => { // Non-null DataAnnotationLocalizerProvider alone is insufficient to change error message. Assert.Equal("data-val-remote", kvp.Key); Assert.Equal(expected, kvp.Value); }, kvp => { Assert.Equal("data-val-remote-additionalfields", kvp.Key); Assert.Equal("*.Length", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-type", kvp.Key); Assert.Equal("POST", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-url", kvp.Key); Assert.Equal(url, kvp.Value); }); }
public void AddValidation_WithErrorMessageAndDisplayName_SetsAttributesAsExpected() { // Arrange var expected = "Error about 'Display Length' from override."; var attribute = new RemoteAttribute("Action", "Controller") { HttpMethod = "POST", ErrorMessage = "Error about '{0}' from override.", }; var url = "/Controller/Action"; var metadataProvider = new TestModelMetadataProvider(); metadataProvider .ForProperty(typeof(string), nameof(string.Length)) .DisplayDetails(d => d.DisplayName = () => "Display Length"); var context = GetValidationContext(url, metadataProvider); // Act attribute.AddValidation(context); // Assert Assert.Collection( context.Attributes, kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); }, kvp => { Assert.Equal("data-val-remote", kvp.Key); Assert.Equal(expected, kvp.Value); }, kvp => { Assert.Equal("data-val-remote-additionalfields", kvp.Key); Assert.Equal("*.Length", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-type", kvp.Key); Assert.Equal("POST", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-url", kvp.Key); Assert.Equal(url, kvp.Value); }); }
public void AddValidation_WithRoute_CallsUrlHelperWithExpectedValues() { // Arrange var routeName = "RouteName"; var attribute = new RemoteAttribute(routeName); var url = "/my/URL"; var urlHelper = new MockUrlHelper(url, routeName); var context = GetValidationContext(urlHelper); // Act attribute.AddValidation(context); // Assert Assert.Collection( context.Attributes, kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); }, kvp => { Assert.Equal("data-val-remote", kvp.Key); Assert.Equal("'Length' is invalid.", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-additionalfields", kvp.Key); Assert.Equal("*.Length", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-url", kvp.Key); Assert.Equal(url, kvp.Value); }); var routeDictionary = Assert.IsType <RouteValueDictionary>(urlHelper.RouteValues); Assert.Empty(routeDictionary); }
public void AddValidation_WithActionController_PropertiesSet_CallsUrlHelperWithExpectedValues() { // Arrange var attribute = new RemoteAttribute("Action", "Controller") { HttpMethod = "POST", AdditionalFields = "Password,ConfirmPassword", }; var url = "/Controller/Action"; var urlHelper = new MockUrlHelper(url, routeName: null); var context = GetValidationContext(urlHelper); // Act attribute.AddValidation(context); // Assert Assert.Collection( context.Attributes, kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); }, kvp => { Assert.Equal("data-val-remote", kvp.Key); Assert.Equal("'Length' is invalid.", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-additionalfields", kvp.Key); Assert.Equal("*.Length,*.Password,*.ConfirmPassword", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-type", kvp.Key); Assert.Equal("POST", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-url", kvp.Key); Assert.Equal(url, kvp.Value); }); var routeDictionary = Assert.IsType<RouteValueDictionary>(urlHelper.RouteValues); Assert.Equal(2, routeDictionary.Count); Assert.Equal("Action", routeDictionary["action"] as string); Assert.Equal("Controller", routeDictionary["controller"] as string); }
public void AddValidation_WithBadRouteName_Throws() { // Arrange var attribute = new RemoteAttribute("nonexistentRoute"); var context = GetValidationContextWithArea(currentArea: null); // Act & Assert var exception = Assert.Throws<InvalidOperationException>(() => attribute.AddValidation(context)); Assert.Equal("No URL for remote validation could be found.", exception.Message); }
public void AddValidation_WithActionController_FindsControllerInCurrentArea() { // Arrange var attribute = new RemoteAttribute("Action", "Controller"); var context = GetValidationContextWithArea(currentArea: null); // Act attribute.AddValidation(context); // Assert Assert.Collection( context.Attributes, kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); }, kvp => { Assert.Equal("data-val-remote", kvp.Key); Assert.Equal("'Length' is invalid.", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-additionalfields", kvp.Key); Assert.Equal("*.Length", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-url", kvp.Key); Assert.Equal("/UrlEncode[[Controller]]/UrlEncode[[Action]]", kvp.Value); }); }
public void AddValidation_WithErrorMessage_SetsAttributesAsExpected() { // Arrange var expected = "Error about 'Length' from override."; var attribute = new RemoteAttribute("Action", "Controller") { HttpMethod = "POST", ErrorMessage = "Error about '{0}' from override.", }; var url = "/Controller/Action"; var context = GetValidationContext(url); // Act attribute.AddValidation(context); // Assert Assert.Collection( context.Attributes, kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); }, kvp => { Assert.Equal("data-val-remote", kvp.Key); Assert.Equal(expected, kvp.Value); }, kvp => { Assert.Equal("data-val-remote-additionalfields", kvp.Key); Assert.Equal("*.Length", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-type", kvp.Key); Assert.Equal("POST", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-url", kvp.Key); Assert.Equal(url, kvp.Value); }); }
public void AddValidation_WithErrorResourcesLocalizerFactoryAndLocalizerProvider_SetsAttributesAsExpected() { // Arrange var expected = "Error about 'Length' from resources."; var attribute = new RemoteAttribute("Action", "Controller") { HttpMethod = "POST", ErrorMessageResourceName = nameof(Resources.RemoteAttribute_Error), ErrorMessageResourceType = typeof(Resources), }; var url = "/Controller/Action"; var context = GetValidationContextWithLocalizerFactory(url); var localizer = new Mock<IStringLocalizer>(MockBehavior.Strict); var options = context.ActionContext.HttpContext.RequestServices .GetRequiredService<IOptions<MvcDataAnnotationsLocalizationOptions>>(); options.Value.DataAnnotationLocalizerProvider = (type, factory) => localizer.Object; // Act attribute.AddValidation(context); // Assert Assert.Collection( context.Attributes, kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); }, kvp => { // Configuring the attribute using ErrorMessageResource* trumps available IStringLocalizer etc. Assert.Equal("data-val-remote", kvp.Key); Assert.Equal(expected, kvp.Value); }, kvp => { Assert.Equal("data-val-remote-additionalfields", kvp.Key); Assert.Equal("*.Length", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-type", kvp.Key); Assert.Equal("POST", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-url", kvp.Key); Assert.Equal(url, kvp.Value); }); }
public void AddValidation_WithRoute_CallsUrlHelperWithExpectedValues() { // Arrange var routeName = "RouteName"; var attribute = new RemoteAttribute(routeName); var url = "/my/URL"; var urlHelper = new MockUrlHelper(url, routeName); var context = GetValidationContext(urlHelper); // Act attribute.AddValidation(context); // Assert Assert.Collection( context.Attributes, kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); }, kvp => { Assert.Equal("data-val-remote", kvp.Key); Assert.Equal("'Length' is invalid.", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-additionalfields", kvp.Key); Assert.Equal("*.Length", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-url", kvp.Key); Assert.Equal(url, kvp.Value); }); var routeDictionary = Assert.IsType<RouteValueDictionary>(urlHelper.RouteValues); Assert.Empty(routeDictionary); }
public void AddValidation_WithErrorMessageLocalizerFactoryLocalizerProviderAndDisplayName_SetsAttributesAsExpected() { // Arrange var expected = "Error about 'Length' from localizer."; var attribute = new RemoteAttribute("Action", "Controller") { HttpMethod = "POST", ErrorMessage = "Error about '{0}' from override.", }; var url = "/Controller/Action"; var metadataProvider = new TestModelMetadataProvider(); metadataProvider .ForProperty(typeof(string), nameof(string.Length)) .DisplayDetails(d => d.DisplayName = () => "Display Length"); var context = GetValidationContextWithLocalizerFactory(url, metadataProvider); var localizedString = new LocalizedString("Fred", expected); var localizer = new Mock<IStringLocalizer>(MockBehavior.Strict); localizer .Setup(l => l["Error about '{0}' from override.", "Display Length"]) .Returns(localizedString) .Verifiable(); var options = context.ActionContext.HttpContext.RequestServices .GetRequiredService<IOptions<MvcDataAnnotationsLocalizationOptions>>(); options.Value.DataAnnotationLocalizerProvider = (type, factory) => localizer.Object; // Act attribute.AddValidation(context); // Assert localizer.VerifyAll(); Assert.Collection( context.Attributes, kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); }, kvp => { Assert.Equal("data-val-remote", kvp.Key); Assert.Equal(expected, kvp.Value); }, kvp => { Assert.Equal("data-val-remote-additionalfields", kvp.Key); Assert.Equal("*.Length", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-type", kvp.Key); Assert.Equal("POST", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-url", kvp.Key); Assert.Equal(url, kvp.Value); }); }
public void AddValidation_WithErrorMessageAndLocalizerProvider_SetsAttributesAsExpected() { // Arrange var expected = "Error about 'Length' from override."; var attribute = new RemoteAttribute("Action", "Controller") { HttpMethod = "POST", ErrorMessage = "Error about '{0}' from override.", }; var url = "/Controller/Action"; var context = GetValidationContext(url); var options = context.ActionContext.HttpContext.RequestServices .GetRequiredService<IOptions<MvcDataAnnotationsLocalizationOptions>>(); var localizer = new Mock<IStringLocalizer>(MockBehavior.Strict); options.Value.DataAnnotationLocalizerProvider = (type, factory) => localizer.Object; // Act attribute.AddValidation(context); // Assert Assert.Collection( context.Attributes, kvp => { Assert.Equal("data-val", kvp.Key); Assert.Equal("true", kvp.Value); }, kvp => { // Non-null DataAnnotationLocalizerProvider alone is insufficient to change error message. Assert.Equal("data-val-remote", kvp.Key); Assert.Equal(expected, kvp.Value); }, kvp => { Assert.Equal("data-val-remote-additionalfields", kvp.Key); Assert.Equal("*.Length", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-type", kvp.Key); Assert.Equal("POST", kvp.Value); }, kvp => { Assert.Equal("data-val-remote-url", kvp.Key); Assert.Equal(url, kvp.Value); }); }
public void FormatAdditionalFieldsForClientValidation_WithInvalidPropertyName_Throws(string property) { // Arrange var attribute = new RemoteAttribute(routeName: "default"); var expected = "Value cannot be null or empty." + Environment.NewLine + "Parameter name: property"; // Act & Assert var exception = Assert.Throws<ArgumentException>( "property", () => attribute.FormatAdditionalFieldsForClientValidation(property)); Assert.Equal(expected, exception.Message); }