Files
acceptance-tests
data
docs
external
Newtonsoft.Json
api-doc-tools
api-snapshot
aspnetwebstack
packages
src
test
Microsoft.TestCommon
Microsoft.Web.Helpers.Test
Microsoft.Web.Http.Data.Test
Microsoft.Web.Mvc.Test
Microsoft.Web.WebPages.OAuth.Test
SPA.Test
System.Json.Test.Integration
System.Json.Test.Unit
System.Net.Http.Formatting.Test.Integration
System.Net.Http.Formatting.Test.Unit
System.Web.Helpers.Test
System.Web.Http.Integration.Test
System.Web.Http.SelfHost.Test
System.Web.Http.Test
System.Web.Http.WebHost.Test
System.Web.Mvc.Test
Ajax
Async
ExpressionUtil
Html
Properties
Razor
Test
AcceptVerbsAttributeTest.cs
ActionDescriptorTest.cs
ActionExecutedContextTest.cs
ActionExecutingContextTest.cs
ActionFilterAttributeTest.cs
ActionMethodDispatcherCacheTest.cs
ActionMethodDispatcherTest.cs
ActionMethodSelectorTest.cs
ActionNameAttributeTest.cs
AdditionalMetadataAttributeTest.cs
AjaxHelperTest.cs
AjaxHelper`1Test.cs
AjaxRequestExtensionsTest.cs
AllowHtmlAttributeTest.cs
AreaHelpersTest.cs
AreaRegistrationContextTest.cs
AreaRegistrationTest.cs
AssociatedMetadataProviderTest.cs
AssociatedValidatorProviderTest.cs
AsyncControllerTest.cs
AsyncTimeoutAttributeTest.cs
AuthorizationContextTest.cs
AuthorizeAttributeTest.cs
BindAttributeTest.cs
BuildManagerCompiledViewTest.cs
BuildManagerViewEngineTest.cs
ByteArrayModelBinderTest.cs
CachedAssociatedMetadataProviderTest.cs
CachedDataAnnotationsModelMetadataProviderTest.cs
CancellationTokenModelBinderTest.cs
ChildActionOnlyAttributeTest.cs
ChildActionValueProviderFactoryTest.cs
ClientDataTypeModelValidatorProviderTest.cs
CompareAttributeTest.cs
ContentResultTest.cs
ControllerActionInvokerTest.cs.REMOVED.git-id
ControllerBaseTest.cs
ControllerBuilderTest.cs
ControllerContextTest.cs
ControllerDescriptorCacheTest.cs
ControllerDescriptorTest.cs
ControllerInstanceFilterProviderTest.cs
ControllerTest.cs
DataAnnotationsModelMetadataProviderTest.cs
DataAnnotationsModelMetadataProviderTestBase.cs
DataAnnotationsModelValidatorProviderTest.cs
DataAnnotationsModelValidatorTest.cs
DataErrorInfoModelValidatorProviderTest.cs
DataTypeUtilTest.cs
DefaultControllerFactoryTest.cs
DefaultModelBinderTest.cs.REMOVED.git-id
DefaultViewLocationCacheTest.cs
DependencyResolverTest.cs
DescriptorUtilTest.cs
DictionaryHelpersTest.cs
DictionaryValueProviderTest.cs
DynamicViewDataDictionaryTest.cs
EmptyModelValidatorProviderTest.cs
ExceptionContextTest.cs
ExpressionHelperTest.cs
FieldValidationMetadataTest.cs
FileContentResultTest.cs
FilePathResultTest.cs
FileResultTest.cs
FileStreamResultTest.cs
FilterAttributeFilterProviderTest.cs
FilterInfoTest.cs
FilterProviderCollectionTest.cs
FilterProvidersTest.cs
FilterTest.cs
FormCollectionTest.cs
FormContextTest.cs
FormValueProviderFactoryTest.cs
GlobalFilterCollectionTest.cs
HandleErrorAttributeTest.cs
HandleErrorInfoTest.cs
HtmlHelperTest.cs
HtmlHelper`1Test.cs
HttpDeleteAttributeTest.cs
HttpFileCollectionValueProviderFactoryTest.cs
HttpFileCollectionValueProviderTest.cs
HttpGetAttributeTest.cs
HttpHandlerUtilTest.cs
HttpHeadAttributeTest.cs
HttpNotFoundResultTest.cs
HttpOptionsAttributeTest.cs
HttpPatchAttributeTest.cs
HttpPostAttributeTest.cs
HttpPostedFileBaseModelBinderTest.cs
HttpPutAttributeTest.cs
HttpRequestExtensionsTest.cs
HttpStatusCodeResultTest.cs
HttpUnauthorizedResultTest.cs
HttpVerbAttributeHelper.cs
JavaScriptResultTest.cs
JsonResultTest.cs
JsonValueProviderFactoryTest.cs
LinqBinaryModelBinderTest.cs
MockBuildManager.cs
MockHelpers.cs
MockableUnvalidatedRequestValues.cs
ModelBinderAttributeTest.cs
ModelBinderDictionaryTest.cs
ModelBinderProviderCollectionTest.cs
ModelBinderProvidersTest.cs
ModelBindersTest.cs
ModelBindingContextTest.cs
ModelClientValidationRuleTest.cs
ModelErrorCollectionTest.cs
ModelErrorTest.cs
ModelMetadataProvidersTest.cs
ModelMetadataTest.cs
ModelStateDictionaryTest.cs
ModelStateTest.cs
ModelValidationResultTest.cs
ModelValidatorProviderCollectionTest.cs
ModelValidatorProvidersTest.cs
ModelValidatorTest.cs
MultiSelectListTest.cs
MultiServiceResolverTest.cs
MvcHandlerTest.cs
MvcHtmlStringTest.cs
MvcHttpHandlerTest.cs
MvcRouteHandlerTest.cs
MvcTestHelper.cs
MvcWebRazorHostFactoryTest.cs
NameValueCollectionExtensionsTest.cs
NameValueCollectionValueProviderTest.cs
NoAsyncTimeoutAttributeTest.cs
NonActionAttributeTest.cs
OutputCacheAttributeTest.cs
ParameterBindingInfoTest.cs
ParameterDescriptorTest.cs
ParameterInfoUtilTest.cs
PartialViewResultTest.cs
PathHelpersTest.cs
PreApplicationStartCodeTest.cs
QueryStringValueProviderFactoryTest.cs
RangeAttributeAdapterTest.cs
RazorViewEngineTest.cs
RazorViewTest.cs
ReaderWriterCacheTest.cs
RedirectResultTest.cs
RedirectToRouteResultTest.cs
ReflectedActionDescriptorTest.cs
ReflectedControllerDescriptorTest.cs
ReflectedParameterBindingInfoTest.cs
ReflectedParameterDescriptorTest.cs
RegularExpressionAttributeAdapterTest.cs
RemoteAttributeTest.cs
RequireHttpsAttributeTest.cs
RequiredAttributeAdapterTest.cs
ResultExecutedContextTest.cs
ResultExecutingContextTest.cs
RouteCollectionExtensionsTest.cs
RouteDataValueProviderFactoryTest.cs
SelectListTest.cs
SessionStateTempDataProviderTest.cs
SingleServiceResolverTest.cs
StringLengthAttributeAdapterTest.cs
TempDataDictionaryTest.cs
TypeCacheSerializerTest.cs
TypeCacheUtilTest.cs
TypeHelpersTest.cs
UrlHelperTest.cs
UrlParameterTest.cs
UrlRewriterHelperTest.cs
ValidatableObjectAdapterTest.cs
ValidateAntiForgeryTokenAttributeTest.cs
ValidateInputAttributeTest.cs
ValueProviderCollectionTest.cs
ValueProviderDictionaryTest.cs
ValueProviderFactoriesTest.cs
ValueProviderFactoryCollectionTest.cs
ValueProviderResultTest.cs
ValueProviderUtilTest.cs
ViewContextTest.cs
ViewDataDictionaryTest.cs
ViewDataInfoTest.cs
ViewEngineCollectionTest.cs
ViewEngineResultTest.cs
ViewEnginesTest.cs
ViewMasterPageControlBuilderTest.cs
ViewMasterPageTest.cs
ViewPageControlBuilderTest.cs
ViewPageTest.cs
ViewResultBaseTest.cs
ViewResultTest.cs
ViewStartPageTest.cs
ViewTypeParserFilterTest.cs
ViewUserControlControlBuilderTest.cs
ViewUserControlTest.cs
VirtualPathProviderViewEngineTest.cs
WebFormViewEngineTest.cs
WebFormViewTest.cs
Util
System.Web.Mvc.Test.csproj
packages.config
System.Web.Razor.Test
System.Web.WebPages.Administration.Test
System.Web.WebPages.Deployment.Test
System.Web.WebPages.Razor.Test
System.Web.WebPages.Test
WebMatrix.Data.Test
WebMatrix.WebData.Test
Settings.StyleCop
tools
.gitattributes
.gitignore
License.txt
README.md
Runtime.msbuild
Runtime.sln
Runtime.xunit
Settings.StyleCop
build.cmd
binary-reference-assemblies
bockbuild
boringssl
cecil
cecil-legacy
corefx
corert
helix-binaries
ikdasm
ikvm
illinker-test-assets
linker
llvm
nuget-buildtasks
nunit-lite
roslyn-binaries
rx
xunit-binaries
how-to-bump-roslyn-binaries.md
ikvm-native
libgc
llvm
m4
man
mcs
mk
mono
msvc
po
runtime
samples
scripts
support
tools
COPYING.LIB
LICENSE
Makefile.am
Makefile.in
NEWS
README.md
acinclude.m4
aclocal.m4
autogen.sh
code_of_conduct.md
compile
config.guess
config.h.in
config.rpath
config.sub
configure.REMOVED.git-id
configure.ac.REMOVED.git-id
depcomp
install-sh
ltmain.sh.REMOVED.git-id
missing
mkinstalldirs
mono-uninstalled.pc.in
test-driver
winconfig.h
linux-packaging-mono/external/aspnetwebstack/test/System.Web.Mvc.Test/Test/ModelMetadataTest.cs

895 lines
35 KiB
C#
Raw Normal View History

// 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 System.Linq.Expressions;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Mvc.Test
{
public class ModelMetadataTest
{
// Guard clauses
[Fact]
public void NullProviderThrows()
{
// Act & Assert
Assert.ThrowsArgumentNull(
() => new ModelMetadata(null /* provider */, null /* containerType */, null /* model */, typeof(object), null /* propertyName */),
"provider");
}
[Fact]
public void NullTypeThrows()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
// Act & Assert
Assert.ThrowsArgumentNull(
() => new ModelMetadata(provider.Object, null /* containerType */, null /* model */, null /* modelType */, null /* propertyName */),
"modelType");
}
// Constructor
[Fact]
public void DefaultValues()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
// Act
ModelMetadata metadata = new ModelMetadata(provider.Object, typeof(Exception), () => "model", typeof(string), "propertyName");
// Assert
Assert.Equal(typeof(Exception), metadata.ContainerType);
Assert.True(metadata.ConvertEmptyStringToNull);
Assert.Null(metadata.DataTypeName);
Assert.Null(metadata.Description);
Assert.Null(metadata.DisplayFormatString);
Assert.Null(metadata.DisplayName);
Assert.Null(metadata.EditFormatString);
Assert.False(metadata.HideSurroundingHtml);
Assert.Equal("model", metadata.Model);
Assert.Equal(typeof(string), metadata.ModelType);
Assert.Null(metadata.NullDisplayText);
Assert.Equal(10000, metadata.Order);
Assert.Equal("propertyName", metadata.PropertyName);
Assert.False(metadata.IsReadOnly);
Assert.True(metadata.RequestValidationEnabled);
Assert.Null(metadata.ShortDisplayName);
Assert.True(metadata.ShowForDisplay);
Assert.True(metadata.ShowForEdit);
Assert.Null(metadata.TemplateHint);
Assert.Null(metadata.Watermark);
}
// IsComplexType
struct IsComplexTypeModel
{
}
[Fact]
public void IsComplexTypeTests()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
// Act & Assert
Assert.True(new ModelMetadata(provider.Object, null, null, typeof(Object), null).IsComplexType);
Assert.False(new ModelMetadata(provider.Object, null, null, typeof(string), null).IsComplexType);
Assert.True(new ModelMetadata(provider.Object, null, null, typeof(IDisposable), null).IsComplexType);
Assert.False(new ModelMetadata(provider.Object, null, null, typeof(Nullable<int>), null).IsComplexType);
Assert.False(new ModelMetadata(provider.Object, null, null, typeof(int), null).IsComplexType);
Assert.True(new ModelMetadata(provider.Object, null, null, typeof(IsComplexTypeModel), null).IsComplexType);
Assert.True(new ModelMetadata(provider.Object, null, null, typeof(Nullable<IsComplexTypeModel>), null).IsComplexType);
}
// IsNullableValueType
[Fact]
public void IsNullableValueTypeTests()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
// Act & Assert
Assert.False(new ModelMetadata(provider.Object, null, null, typeof(string), null).IsNullableValueType);
Assert.False(new ModelMetadata(provider.Object, null, null, typeof(IDisposable), null).IsNullableValueType);
Assert.True(new ModelMetadata(provider.Object, null, null, typeof(Nullable<int>), null).IsNullableValueType);
Assert.False(new ModelMetadata(provider.Object, null, null, typeof(int), null).IsNullableValueType);
}
// IsRequired
[Fact]
public void IsRequiredTests()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
// Act & Assert
Assert.False(new ModelMetadata(provider.Object, null, null, typeof(string), null).IsRequired); // Reference type not required
Assert.False(new ModelMetadata(provider.Object, null, null, typeof(IDisposable), null).IsRequired); // Interface not required
Assert.False(new ModelMetadata(provider.Object, null, null, typeof(Nullable<int>), null).IsRequired); // Nullable value type not required
Assert.True(new ModelMetadata(provider.Object, null, null, typeof(int), null).IsRequired); // Value type required
Assert.True(new ModelMetadata(provider.Object, null, null, typeof(DayOfWeek), null).IsRequired); // Enum (implicit value type) is required
}
// Properties
[Fact]
public void PropertiesCallsProvider()
{
// Arrange
Type modelType = typeof(string);
List<ModelMetadata> propertyMetadata = new List<ModelMetadata>();
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
ModelMetadata metadata = new ModelMetadata(provider.Object, null, null, modelType, null);
provider.Setup(p => p.GetMetadataForProperties(null, modelType))
.Returns(propertyMetadata)
.Verifiable();
// Act
IEnumerable<ModelMetadata> result = metadata.Properties;
// Assert
Assert.Equal(propertyMetadata, result.ToList());
provider.Verify();
}
[Fact]
public void PropertiesUsesRealModelTypeRatherThanPassedModelType()
{
// Arrange
string model = "String Value";
Expression<Func<object, object>> accessor = _ => model;
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(accessor, new ViewDataDictionary<object>());
// Act
IEnumerable<ModelMetadata> result = metadata.Properties;
// Assert
Assert.Equal("Length", result.Single().PropertyName);
}
[Fact]
public void PropertiesAreSortedByOrder()
{
// Arrange
Type modelType = typeof(string);
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
List<ModelMetadata> propertyMetadata = new List<ModelMetadata>
{
new ModelMetadata(provider.Object, null, () => 1, typeof(int), null) { Order = 20 },
new ModelMetadata(provider.Object, null, () => 2, typeof(int), null) { Order = 30 },
new ModelMetadata(provider.Object, null, () => 3, typeof(int), null) { Order = 10 },
};
ModelMetadata metadata = new ModelMetadata(provider.Object, null, null, modelType, null);
provider.Setup(p => p.GetMetadataForProperties(null, modelType))
.Returns(propertyMetadata)
.Verifiable();
// Act
List<ModelMetadata> result = metadata.Properties.ToList();
// Assert
Assert.Equal(3, result.Count);
Assert.Equal(3, result[0].Model);
Assert.Equal(1, result[1].Model);
Assert.Equal(2, result[2].Model);
}
[Fact]
public void PropertiesListGetsResetWhenModelGetsReset()
{ // Dev10 Bug #923263
// Arrange
var provider = new DataAnnotationsModelMetadataProvider();
var metadata = new ModelMetadata(provider, null, () => new Class1(), typeof(Class1), null);
// Act
ModelMetadata[] originalProps = metadata.Properties.ToArray();
metadata.Model = new Class2();
ModelMetadata[] newProps = metadata.Properties.ToArray();
// Assert
ModelMetadata originalProp = Assert.Single(originalProps);
Assert.Equal(typeof(string), originalProp.ModelType);
Assert.Equal("Prop1", originalProp.PropertyName);
ModelMetadata newProp = Assert.Single(newProps);
Assert.Equal(typeof(int), newProp.ModelType);
Assert.Equal("Prop2", newProp.PropertyName);
}
class Class1
{
public string Prop1 { get; set; }
}
class Class2
{
public int Prop2 { get; set; }
}
// SimpleDisplayText
[Fact]
public void SimpleDisplayTextReturnsNullDisplayTextForNullModel()
{
// Arrange
string nullText = "(null)";
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
ModelMetadata metadata = new ModelMetadata(provider.Object, null, null, typeof(object), null) { NullDisplayText = nullText };
// Act
string result = metadata.SimpleDisplayText;
// Assert
Assert.Equal(nullText, result);
}
private class SimpleDisplayTextModelWithToString
{
public override string ToString()
{
return "Custom ToString Value";
}
}
[Fact]
public void SimpleDisplayTextReturnsToStringValueWhenOverridden()
{
// Arrange
SimpleDisplayTextModelWithToString model = new SimpleDisplayTextModelWithToString();
EmptyModelMetadataProvider provider = new EmptyModelMetadataProvider();
ModelMetadata metadata = new ModelMetadata(provider, null, () => model, typeof(SimpleDisplayTextModelWithToString), null);
// Act
string result = metadata.SimpleDisplayText;
// Assert
Assert.Equal(model.ToString(), result);
}
private class SimpleDisplayTextModelWithoutToString
{
public string FirstProperty { get; set; }
public int SecondProperty { get; set; }
}
[Fact]
public void SimpleDisplayTextReturnsFirstPropertyValueForNonNullModel()
{
// Arrange
SimpleDisplayTextModelWithoutToString model = new SimpleDisplayTextModelWithoutToString
{
FirstProperty = "First Property Value"
};
EmptyModelMetadataProvider provider = new EmptyModelMetadataProvider();
ModelMetadata metadata = new ModelMetadata(provider, null, () => model, typeof(SimpleDisplayTextModelWithoutToString), null);
// Act
string result = metadata.SimpleDisplayText;
// Assert
Assert.Equal(model.FirstProperty, result);
}
[Fact]
public void SimpleDisplayTextReturnsFirstPropertyNullDisplayTextForNonNullModelWithNullDisplayColumnPropertyValue()
{
// Arrange
SimpleDisplayTextModelWithoutToString model = new SimpleDisplayTextModelWithoutToString();
EmptyModelMetadataProvider propertyProvider = new EmptyModelMetadataProvider();
ModelMetadata propertyMetadata = propertyProvider.GetMetadataForProperty(() => model.FirstProperty, typeof(SimpleDisplayTextModelWithoutToString), "FirstProperty");
propertyMetadata.NullDisplayText = "Null Display Text";
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
provider.Setup(p => p.GetMetadataForProperties(model, typeof(SimpleDisplayTextModelWithoutToString)))
.Returns(new[] { propertyMetadata });
ModelMetadata metadata = new ModelMetadata(provider.Object, null, () => model, typeof(SimpleDisplayTextModelWithoutToString), null);
// Act
string result = metadata.SimpleDisplayText;
// Assert
Assert.Equal(propertyMetadata.NullDisplayText, result);
}
private class SimpleDisplayTextModelWithNoProperties
{
}
[Fact]
public void SimpleDisplayTextReturnsEmptyStringForNonNullModelWithNoVisibleProperties()
{
// Arrange
SimpleDisplayTextModelWithNoProperties model = new SimpleDisplayTextModelWithNoProperties();
EmptyModelMetadataProvider provider = new EmptyModelMetadataProvider();
ModelMetadata metadata = new ModelMetadata(provider, null, () => model, typeof(SimpleDisplayTextModelWithNoProperties), null);
// Act
string result = metadata.SimpleDisplayText;
// Assert
Assert.Equal(String.Empty, result);
}
private class ObjectWithToStringOverride
{
private string _toStringValue;
public ObjectWithToStringOverride(string toStringValue)
{
_toStringValue = toStringValue;
}
public override string ToString()
{
return _toStringValue;
}
}
[Fact]
public void SimpleDisplayTextReturnsToStringOfModelForNonNullModel()
{
// Arrange
string toStringText = "text from ToString()";
ObjectWithToStringOverride model = new ObjectWithToStringOverride(toStringText);
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
ModelMetadata metadata = new ModelMetadata(provider.Object, null, () => model, typeof(ObjectWithToStringOverride), null);
// Act
string result = metadata.SimpleDisplayText;
// Assert
Assert.Equal(toStringText, result);
}
[Fact]
public void SimpleDisplayTextReturnsEmptyStringForNonNullModelWithToStringNull()
{
// Arrange
string toStringText = null;
ObjectWithToStringOverride model = new ObjectWithToStringOverride(toStringText);
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
ModelMetadata metadata = new ModelMetadata(provider.Object, null, () => model, typeof(ObjectWithToStringOverride), null);
// Act
string result = metadata.SimpleDisplayText;
// Assert
Assert.Equal(String.Empty, result);
}
// FromStringExpression()
[Fact]
public void FromStringExpressionGuardClauses()
{
// Null expression throws
Assert.ThrowsArgumentNull(
() => ModelMetadata.FromStringExpression(null, new ViewDataDictionary()),
"expression");
// Null view data dictionary throws
Assert.ThrowsArgumentNull(
() => ModelMetadata.FromStringExpression("expression", null),
"viewData");
}
[Fact]
public void FromStringExpressionEmptyExpressionReturnsExistingModelMetadata()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
ModelMetadata metadata = new ModelMetadata(provider.Object, null, null, typeof(object), null);
ViewDataDictionary viewData = new ViewDataDictionary();
viewData.ModelMetadata = metadata;
// Act
ModelMetadata result = ModelMetadata.FromStringExpression(String.Empty, viewData, provider.Object);
// Assert
Assert.Same(metadata, result);
}
[Fact]
public void FromStringExpressionItemNotFoundInViewData()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
ViewDataDictionary viewData = new ViewDataDictionary();
provider.Setup(p => p.GetMetadataForType(It.IsAny<Func<object>>(), It.IsAny<Type>()))
.Callback<Func<object>, Type>((accessor, type) =>
{
Assert.Null(accessor);
Assert.Equal(typeof(string), type); // Don't know the type, must fall back on string
})
.Returns(() => null)
.Verifiable();
// Act
ModelMetadata.FromStringExpression("UnknownObject", viewData, provider.Object);
// Assert
provider.Verify();
}
[Fact]
public void FromStringExpressionNullItemFoundAtRootOfViewData()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
ViewDataDictionary viewData = new ViewDataDictionary();
viewData["Object"] = null;
provider.Setup(p => p.GetMetadataForType(It.IsAny<Func<object>>(), It.IsAny<Type>()))
.Callback<Func<object>, Type>((accessor, type) =>
{
Assert.Null(accessor());
Assert.Equal(typeof(string), type); // Don't know the type, must fall back on string
})
.Returns(() => null)
.Verifiable();
// Act
ModelMetadata.FromStringExpression("Object", viewData, provider.Object);
// Assert
provider.Verify();
}
[Fact]
public void FromStringExpressionNonNullItemFoundAtRootOfViewData()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
object model = new object();
ViewDataDictionary viewData = new ViewDataDictionary();
viewData["Object"] = model;
provider.Setup(p => p.GetMetadataForType(It.IsAny<Func<object>>(), It.IsAny<Type>()))
.Callback<Func<object>, Type>((accessor, type) =>
{
Assert.Same(model, accessor());
Assert.Equal(typeof(object), type);
})
.Returns(() => null)
.Verifiable();
// Act
ModelMetadata.FromStringExpression("Object", viewData, provider.Object);
// Assert
provider.Verify();
}
[Fact]
public void FromStringExpressionNullItemFoundOnPropertyOfItemInViewData()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
DummyModelContainer model = new DummyModelContainer();
ViewDataDictionary viewData = new ViewDataDictionary();
viewData["Object"] = model;
provider.Setup(p => p.GetMetadataForProperty(It.IsAny<Func<object>>(), It.IsAny<Type>(), It.IsAny<string>()))
.Callback<Func<object>, Type, string>((accessor, type, propertyName) =>
{
Assert.Null(accessor());
Assert.Equal(typeof(DummyModelContainer), type);
Assert.Equal("Model", propertyName);
})
.Returns(() => null)
.Verifiable();
// Act
ModelMetadata.FromStringExpression("Object.Model", viewData, provider.Object);
// Assert
provider.Verify();
}
[Fact]
public void FromStringExpressionNonNullItemFoundOnPropertyOfItemInViewData()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
DummyModelContainer model = new DummyModelContainer { Model = new DummyContactModel() };
ViewDataDictionary viewData = new ViewDataDictionary();
viewData["Object"] = model;
provider.Setup(p => p.GetMetadataForProperty(It.IsAny<Func<object>>(), It.IsAny<Type>(), It.IsAny<string>()))
.Callback<Func<object>, Type, string>((accessor, type, propertyName) =>
{
Assert.Same(model.Model, accessor());
Assert.Equal(typeof(DummyModelContainer), type);
Assert.Equal("Model", propertyName);
})
.Returns(() => null)
.Verifiable();
// Act
ModelMetadata.FromStringExpression("Object.Model", viewData, provider.Object);
// Assert
provider.Verify();
}
[Fact]
public void FromStringExpressionWithNullModelButValidModelMetadataShouldReturnProperPropertyMetadata()
{
// Arrange
ViewDataDictionary viewData = new ViewDataDictionary();
viewData.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, typeof(DummyContactModel));
// Act
ModelMetadata result = ModelMetadata.FromStringExpression("NullableIntValue", viewData);
// Assert
Assert.Null(result.Model);
Assert.Equal(typeof(Nullable<int>), result.ModelType);
Assert.Equal("NullableIntValue", result.PropertyName);
Assert.Equal(typeof(DummyContactModel), result.ContainerType);
}
[Fact]
public void FromStringExpressionValueInModelProperty()
{
// Arrange
DummyContactModel model = new DummyContactModel { FirstName = "John" };
ViewDataDictionary viewData = new ViewDataDictionary(model);
// Act
ModelMetadata metadata = ModelMetadata.FromStringExpression("FirstName", viewData);
// Assert
Assert.Equal("John", metadata.Model);
}
[Fact]
public void FromStringExpressionValueInViewDataOverridesValueFromModelProperty()
{
// Arrange
DummyContactModel model = new DummyContactModel { FirstName = "John" };
ViewDataDictionary viewData = new ViewDataDictionary(model);
viewData["FirstName"] = "Jim";
// Act
ModelMetadata metadata = ModelMetadata.FromStringExpression("FirstName", viewData);
// Assert
Assert.Equal("Jim", metadata.Model);
}
// FromLambdaExpression()
[Fact]
public void FromLambdaExpressionGuardClauseTests()
{
// Null expression throws
Assert.ThrowsArgumentNull(
() => ModelMetadata.FromLambdaExpression<string, object>(null, new ViewDataDictionary<string>()),
"expression");
// Null view data throws
Assert.ThrowsArgumentNull(
() => ModelMetadata.FromLambdaExpression<string, object>(m => m, null),
"viewData");
// Unsupported expression type throws
Assert.Throws<InvalidOperationException>(
() => ModelMetadata.FromLambdaExpression<string, object>(m => new Object(), new ViewDataDictionary<string>()),
"Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.");
}
[Fact]
public void FromLambdaExpressionModelIdentityExpressionReturnsExistingModelMetadata()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
ModelMetadata metadata = new ModelMetadata(provider.Object, null, null, typeof(object), null);
ViewDataDictionary<object> viewData = new ViewDataDictionary<object>();
viewData.ModelMetadata = metadata;
// Act
ModelMetadata result = ModelMetadata.FromLambdaExpression<object, object>(m => m, viewData, provider.Object);
// Assert
Assert.Same(metadata, result);
}
[Fact]
public void FromLambdaExpressionPropertyExpressionFromParameter()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
DummyContactModel model = new DummyContactModel { FirstName = "Test" };
ViewDataDictionary<DummyContactModel> viewData = new ViewDataDictionary<DummyContactModel>(model);
provider.Setup(p => p.GetMetadataForProperty(It.IsAny<Func<object>>(), It.IsAny<Type>(), It.IsAny<string>()))
.Callback<Func<object>, Type, string>((accessor, type, propertyName) =>
{
Assert.Equal("Test", accessor());
Assert.Equal(typeof(DummyContactModel), type);
Assert.Equal("FirstName", propertyName);
})
.Returns(() => null)
.Verifiable();
// Act
ModelMetadata.FromLambdaExpression<DummyContactModel, string>(m => m.FirstName, viewData, provider.Object);
// Assert
provider.Verify();
}
[Fact]
public void FromLambdaExpressionPropertyExpressionFromClosureValue()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
DummyContactModel model = new DummyContactModel { FirstName = "Test" };
ViewDataDictionary<object> viewData = new ViewDataDictionary<object>();
provider.Setup(p => p.GetMetadataForProperty(It.IsAny<Func<object>>(), It.IsAny<Type>(), It.IsAny<string>()))
.Callback<Func<object>, Type, string>((accessor, type, propertyName) =>
{
Assert.Equal("Test", accessor());
Assert.Equal(typeof(DummyContactModel), type);
Assert.Equal("FirstName", propertyName);
})
.Returns(() => null)
.Verifiable();
// Act
ModelMetadata.FromLambdaExpression<object, string>(m => model.FirstName, viewData, provider.Object);
// Assert
provider.Verify();
}
[Fact]
public void FromLambdaExpressionFieldExpressionFromParameter()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
DummyContactModel model = new DummyContactModel { IntField = 42 };
ViewDataDictionary<DummyContactModel> viewData = new ViewDataDictionary<DummyContactModel>(model);
provider.Setup(p => p.GetMetadataForType(It.IsAny<Func<object>>(), It.IsAny<Type>()))
.Callback<Func<object>, Type>((accessor, type) =>
{
Assert.Equal(42, accessor());
Assert.Equal(typeof(int), type);
})
.Returns(() => null)
.Verifiable();
// Act
ModelMetadata.FromLambdaExpression<DummyContactModel, int>(m => m.IntField, viewData, provider.Object);
// Assert
provider.Verify();
}
[Fact]
public void FromLambdaExpressionFieldExpressionFromFieldOfClosureValue()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
DummyContactModel model = new DummyContactModel { IntField = 42 };
ViewDataDictionary<object> viewData = new ViewDataDictionary<object>();
provider.Setup(p => p.GetMetadataForType(It.IsAny<Func<object>>(), It.IsAny<Type>()))
.Callback<Func<object>, Type>((accessor, type) =>
{
Assert.Equal(42, accessor());
Assert.Equal(typeof(int), type);
})
.Returns(() => null)
.Verifiable();
// Act
ModelMetadata.FromLambdaExpression<object, int>(m => model.IntField, viewData, provider.Object);
// Assert
provider.Verify();
}
[Fact]
public void FromLambdaExpressionFieldExpressionFromClosureValue()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
DummyContactModel model = new DummyContactModel();
ViewDataDictionary<object> viewData = new ViewDataDictionary<object>();
provider.Setup(p => p.GetMetadataForType(It.IsAny<Func<object>>(), It.IsAny<Type>()))
.Callback<Func<object>, Type>((accessor, type) =>
{
Assert.Same(model, accessor());
Assert.Equal(typeof(DummyContactModel), type);
})
.Returns(() => null)
.Verifiable();
// Act
ModelMetadata.FromLambdaExpression<object, DummyContactModel>(m => model, viewData, provider.Object);
// Assert
provider.Verify();
}
[Fact]
public void FromLambdaExpressionSingleParameterClassIndexer()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
DummyContactModel model = new DummyContactModel();
ViewDataDictionary<DummyContactModel> viewData = new ViewDataDictionary<DummyContactModel>(model);
provider.Setup(p => p.GetMetadataForType(It.IsAny<Func<object>>(), It.IsAny<Type>()))
.Callback<Func<object>, Type>((accessor, type) =>
{
Assert.Equal("Indexed into 42", accessor());
Assert.Equal(typeof(string), type);
})
.Returns(() => null)
.Verifiable();
// Act
ModelMetadata.FromLambdaExpression<DummyContactModel, string>(m => m[42], viewData, provider.Object);
// Assert
provider.Verify();
}
[Fact]
public void FromLambdaExpressionSingleDimensionArrayIndex()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
DummyContactModel model = new DummyContactModel { Array = new[] { 4, 8, 15, 16, 23, 42 } };
ViewDataDictionary<DummyContactModel> viewData = new ViewDataDictionary<DummyContactModel>(model);
provider.Setup(p => p.GetMetadataForType(It.IsAny<Func<object>>(), It.IsAny<Type>()))
.Callback<Func<object>, Type>((accessor, type) =>
{
Assert.Equal(16, accessor());
Assert.Equal(typeof(int), type);
})
.Returns(() => null)
.Verifiable();
// Act
ModelMetadata.FromLambdaExpression<DummyContactModel, int>(m => m.Array[3], viewData, provider.Object);
// Assert
provider.Verify();
}
[Fact]
public void FromLambdaExpressionNullReferenceExceptionsInPropertyExpressionPreserveAllExpressionInformation()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
ViewDataDictionary<DummyContactModel> viewData = new ViewDataDictionary<DummyContactModel>();
provider.Setup(p => p.GetMetadataForProperty(It.IsAny<Func<object>>(), It.IsAny<Type>(), It.IsAny<string>()))
.Callback<Func<object>, Type, string>((accessor, type, propertyName) =>
{
Assert.Null(accessor());
Assert.Equal(typeof(DummyContactModel), type);
Assert.Equal("FirstName", propertyName);
})
.Returns(() => null)
.Verifiable();
// Act
ModelMetadata.FromLambdaExpression<DummyContactModel, string>(m => m.FirstName, viewData, provider.Object);
// Assert
provider.Verify();
}
[Fact]
public void FromLambdaExpressionSetsContainerTypeToDerivedMostType()
{ // Dev10 Bug #868619
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
ViewDataDictionary<DerivedModel> viewData = new ViewDataDictionary<DerivedModel>();
provider.Setup(p => p.GetMetadataForProperty(It.IsAny<Func<object>>(), It.IsAny<Type>(), It.IsAny<string>()))
.Callback<Func<object>, Type, string>((accessor, type, propertyName) =>
{
Assert.Null(accessor());
Assert.Equal(typeof(DerivedModel), type);
Assert.Equal("MyProperty", propertyName);
})
.Returns(() => null)
.Verifiable();
// Act
ModelMetadata.FromLambdaExpression<DerivedModel, string>(m => m.MyProperty, viewData, provider.Object);
// Assert
provider.Verify();
}
private class BaseModel
{
public virtual string MyProperty { get; set; }
}
private class DerivedModel : BaseModel
{
[Required]
public override string MyProperty
{
get { return base.MyProperty; }
set { base.MyProperty = value; }
}
}
// GetDisplayName()
[Fact]
public void ReturnsDisplayNameWhenSet()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
ModelMetadata metadata = new ModelMetadata(provider.Object, null, null, typeof(object), "PropertyName") { DisplayName = "Display Name" };
// Act
string result = metadata.GetDisplayName();
// Assert
Assert.Equal("Display Name", result);
}
[Fact]
public void ReturnsPropertyNameWhenSetAndDisplayNameIsNull()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
ModelMetadata metadata = new ModelMetadata(provider.Object, null, null, typeof(object), "PropertyName");
// Act
string result = metadata.GetDisplayName();
// Assert
Assert.Equal("PropertyName", result);
}
[Fact]
public void ReturnsTypeNameWhenPropertyNameAndDisplayNameAreNull()
{
// Arrange
Mock<ModelMetadataProvider> provider = new Mock<ModelMetadataProvider>();
ModelMetadata metadata = new ModelMetadata(provider.Object, null, null, typeof(object), null);
// Act
string result = metadata.GetDisplayName();
// Assert
Assert.Equal("Object", result);
}
// Helpers
private class DummyContactModel
{
public int IntField = 0;
public string FirstName { get; set; }
public string LastName { get; set; }
public Nullable<int> NullableIntValue { get; set; }
public int[] Array { get; set; }
public string this[int index]
{
get { return "Indexed into " + index; }
}
}
private class DummyModelContainer
{
public DummyContactModel Model { get; set; }
}
}
}