Adjust tests to handle new `ViewDataDictionary` invariants
- ensure `ViewDataDictionary` constructors are not passed a `null` or `Mock.Of<IModelMetadataProvider>()` instance - `ViewDataDictionary` constructors always use the `IModelMetadataProvider` - `viewData.ModelMetadata` now never `null` - `ViewDataDictionary<int>.Model` no longer throws if read before it's written - `ViewDataDictionary.ModelMetadata` now copied to new instances in fewer cases - e.g. don't use unusual `object` datatype with customized `ModelMetadata`
This commit is contained in:
parent
97aaa7049e
commit
c89bca5924
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
services.Setup(s => s.GetService(typeof(IUrlHelper)))
|
||||
.Returns(Mock.Of<IUrlHelper>());
|
||||
services.Setup(s => s.GetService(typeof(IModelMetadataProvider)))
|
||||
.Returns(Mock.Of<IModelMetadataProvider>());
|
||||
.Returns(new EmptyModelMetadataProvider());
|
||||
|
||||
var httpRequest = Mock.Of<HttpRequest>();
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
|
|
@ -53,7 +53,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
// Arrange
|
||||
var services = new Mock<IServiceProvider>();
|
||||
services.Setup(s => s.GetService(typeof(IModelMetadataProvider)))
|
||||
.Returns(Mock.Of<IModelMetadataProvider>());
|
||||
.Returns(new EmptyModelMetadataProvider());
|
||||
services.Setup(s => s.GetService(typeof(ICompositeViewEngine)))
|
||||
.Returns(Mock.Of<ICompositeViewEngine>());
|
||||
services.Setup(s => s.GetService(typeof(IUrlHelper)))
|
||||
|
|
@ -86,7 +86,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
services.Setup(s => s.GetService(typeof(IUrlHelper)))
|
||||
.Returns(urlHelper);
|
||||
services.Setup(s => s.GetService(typeof(IModelMetadataProvider)))
|
||||
.Returns(Mock.Of<IModelMetadataProvider>());
|
||||
.Returns(new EmptyModelMetadataProvider());
|
||||
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.SetupGet(c => c.RequestServices)
|
||||
|
|
@ -114,7 +114,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
services.Setup(s => s.GetService(typeof(IUrlHelper)))
|
||||
.Returns(Mock.Of<IUrlHelper>());
|
||||
services.Setup(s => s.GetService(typeof(IModelMetadataProvider)))
|
||||
.Returns(Mock.Of<IModelMetadataProvider>());
|
||||
.Returns(new EmptyModelMetadataProvider());
|
||||
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.SetupGet(c => c.Response)
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
var actionContext = new ActionContext(routeContext, new ActionDescriptor());
|
||||
return new ViewContext(actionContext,
|
||||
Mock.Of<IView>(),
|
||||
new ViewDataDictionary(Mock.Of<IModelMetadataProvider>()),
|
||||
new ViewDataDictionary(new EmptyModelMetadataProvider()),
|
||||
TextWriter.Null);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
new DataAnnotationsModelMetadataProvider(),
|
||||
containerType: null,
|
||||
modelAccessor: null,
|
||||
modelType: typeof(object),
|
||||
modelType: typeof(string), // Ensure FromStringExpression() doesn't ignore the ModelMetadata.
|
||||
propertyName: propertyName);
|
||||
|
||||
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
new DataAnnotationsModelMetadataProvider(),
|
||||
containerType: null,
|
||||
modelAccessor: null,
|
||||
modelType: typeof(object),
|
||||
modelType: typeof(string), // Ensure FromStringExpression() doesn't ignore the ModelMetadata.
|
||||
propertyName: propertyName);
|
||||
|
||||
var helper = DefaultTemplatesUtilities.GetHtmlHelper();
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
// Only the ViewDataDictionary should do anything with metadata.
|
||||
provider.Verify(
|
||||
m => m.GetMetadataForType(It.IsAny<Func<object>>(), typeof(DefaultTemplatesUtilities.ObjectTemplateModel)),
|
||||
Times.Once);
|
||||
Times.Exactly(2));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -191,7 +191,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
// Only the ViewDataDictionary should do anything with metadata.
|
||||
provider.Verify(
|
||||
m => m.GetMetadataForType(It.IsAny<Func<object>>(), typeof(DefaultTemplatesUtilities.ObjectTemplateModel)),
|
||||
Times.Once);
|
||||
Times.Exactly(2));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Rendering
|
||||
|
|
@ -12,8 +13,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
{
|
||||
// Arrange (eventually passing null to these consturctors will throw)
|
||||
var context = new ViewContext(new ActionContext(null, null, null), view: null, viewData: null, writer: null);
|
||||
var originalViewData = context.ViewData = new ViewDataDictionary(metadataProvider: null);
|
||||
var replacementViewData = new ViewDataDictionary(metadataProvider: null);
|
||||
var originalViewData = context.ViewData = new ViewDataDictionary(metadataProvider: new EmptyModelMetadataProvider());
|
||||
var replacementViewData = new ViewDataDictionary(metadataProvider: new EmptyModelMetadataProvider());
|
||||
|
||||
// Act
|
||||
context.ViewBag.Hello = "goodbye";
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
// Arrange
|
||||
var viewComponent = new TestViewComponent()
|
||||
{
|
||||
ViewData = new ViewDataDictionary(metadataProvider: null),
|
||||
ViewData = new ViewDataDictionary(metadataProvider: new EmptyModelMetadataProvider()),
|
||||
};
|
||||
|
||||
// Act
|
||||
|
|
@ -35,7 +35,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
// Arrange
|
||||
var viewComponent = new TestViewComponent()
|
||||
{
|
||||
ViewData = new ViewDataDictionary(metadataProvider: null),
|
||||
ViewData = new ViewDataDictionary(metadataProvider: new EmptyModelMetadataProvider()),
|
||||
};
|
||||
|
||||
// Act
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
Assert.NotNull(viewData.ModelState);
|
||||
Assert.NotNull(viewData.TemplateInfo);
|
||||
Assert.Null(viewData.Model);
|
||||
Assert.Null(viewData.ModelMetadata);
|
||||
Assert.NotNull(viewData.ModelMetadata);
|
||||
Assert.Equal(0, viewData.Count);
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
Assert.Same(modelState, viewData.ModelState);
|
||||
Assert.NotNull(viewData.TemplateInfo);
|
||||
Assert.Null(viewData.Model);
|
||||
Assert.Null(viewData.ModelMetadata);
|
||||
Assert.NotNull(viewData.ModelMetadata);
|
||||
Assert.Equal(0, viewData.Count);
|
||||
}
|
||||
|
||||
|
|
@ -53,9 +53,14 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
{
|
||||
// Arrange
|
||||
var metadataProvider = new Mock<IModelMetadataProvider>();
|
||||
metadataProvider.Setup(m => m.GetMetadataForType(It.IsAny<Func<object>>(), typeof(TestModel)))
|
||||
.Returns(new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(TestModel)))
|
||||
.Verifiable();
|
||||
metadataProvider
|
||||
.Setup(m => m.GetMetadataForType(It.IsAny<Func<object>>(), typeof(object)))
|
||||
.Returns(new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(object)))
|
||||
.Verifiable();
|
||||
metadataProvider
|
||||
.Setup(m => m.GetMetadataForType(It.IsAny<Func<object>>(), typeof(TestModel)))
|
||||
.Returns(new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(TestModel)))
|
||||
.Verifiable();
|
||||
var modelState = new ModelStateDictionary();
|
||||
var viewData = new TestViewDataDictionary(metadataProvider.Object, modelState);
|
||||
var model = new TestModel();
|
||||
|
|
@ -134,7 +139,7 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
Assert.NotNull(viewData.ModelState);
|
||||
Assert.NotNull(viewData.TemplateInfo);
|
||||
Assert.Null(viewData.Model);
|
||||
Assert.Null(viewData.ModelMetadata);
|
||||
Assert.NotNull(viewData.ModelMetadata);
|
||||
Assert.Equal("value1", viewData["key1"]);
|
||||
Assert.IsType<CopyOnWriteDictionary<string, object>>(viewData.Data);
|
||||
}
|
||||
|
|
@ -148,45 +153,56 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
source["key1"] = "value1";
|
||||
|
||||
// Act
|
||||
var viewData = new ViewDataDictionary<int>(source, null);
|
||||
var viewData = new ViewDataDictionary<int>(source, model: null);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(viewData.ModelState);
|
||||
Assert.NotNull(viewData.TemplateInfo);
|
||||
Assert.Throws<NullReferenceException>(() => viewData.Model);
|
||||
Assert.Equal(0, viewData.Model);
|
||||
Assert.NotNull(viewData.ModelMetadata);
|
||||
Assert.Equal("value1", viewData["key1"]);
|
||||
Assert.IsType<CopyOnWriteDictionary<string, object>>(viewData.Data);
|
||||
}
|
||||
|
||||
public static TheoryData<Type, object> CopyModelMetadataData
|
||||
{
|
||||
get
|
||||
{
|
||||
// Instances in this data set must have exactly the same type as the corresponding Type. Otherwise
|
||||
// the copy constructor ignores the source ModelMetadata.
|
||||
return new TheoryData<Type, object>
|
||||
{
|
||||
{ typeof(int), 23 },
|
||||
{ typeof(string), "hello" },
|
||||
{ typeof(List<string>), new List<string>() },
|
||||
{ typeof(string[]), new string[0] },
|
||||
{ typeof(Dictionary<string, object>), new Dictionary<string, object>() },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(typeof(int))]
|
||||
[InlineData(typeof(string))]
|
||||
[InlineData(typeof(IEnumerable<string>))]
|
||||
[InlineData(typeof(List<string>))]
|
||||
[InlineData(typeof(string[]))]
|
||||
[InlineData(typeof(Dictionary<string, object>))]
|
||||
public void CopyConstructors_CopyModelMetadata(Type type)
|
||||
[MemberData(nameof(CopyModelMetadataData))]
|
||||
public void CopyConstructors_CopyModelMetadata(Type type, object instance)
|
||||
{
|
||||
// Arrange
|
||||
var metadataProvider = new EmptyModelMetadataProvider();
|
||||
var metadata = metadataProvider.GetMetadataForType(() => null, type);
|
||||
var source = new ViewDataDictionary(metadataProvider)
|
||||
{
|
||||
ModelMetadata = metadata,
|
||||
Model = instance,
|
||||
};
|
||||
|
||||
// Act
|
||||
var viewData1 = new ViewDataDictionary(source);
|
||||
var viewData2 = new ViewDataDictionary(source, model: null);
|
||||
var viewData2 = new ViewDataDictionary(source, model: instance);
|
||||
|
||||
// Assert
|
||||
Assert.Same(metadata, viewData1.ModelMetadata);
|
||||
Assert.Same(metadata, viewData2.ModelMetadata);
|
||||
Assert.Same(source.ModelMetadata, viewData1.ModelMetadata);
|
||||
Assert.Same(source.ModelMetadata, viewData2.ModelMetadata);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CopyConstructors_IgnoreModelMetadata_IfForTypeObject()
|
||||
public void CopyConstructors_CopyModelMetadata_ForTypeObject()
|
||||
{
|
||||
// Arrange
|
||||
var metadataProvider = new EmptyModelMetadataProvider();
|
||||
|
|
@ -201,8 +217,8 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
var viewData2 = new ViewDataDictionary(source, model: null);
|
||||
|
||||
// Assert
|
||||
Assert.Null(viewData1.ModelMetadata);
|
||||
Assert.Null(viewData2.ModelMetadata);
|
||||
Assert.Same(metadata, viewData1.ModelMetadata);
|
||||
Assert.Same(metadata, viewData2.ModelMetadata);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -240,6 +256,28 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
Assert.Equal(expectedType, viewData2.ModelMetadata.RealModelType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CopyConstructors_OverrideSourceMetadata_IfDeclaredTypeChanged()
|
||||
{
|
||||
// Arrange
|
||||
var expectedType = typeof(string);
|
||||
var metadataProvider = new EmptyModelMetadataProvider();
|
||||
var source = new ViewDataDictionary<int>(metadataProvider);
|
||||
|
||||
// Act
|
||||
var viewData1 = new ViewDataDictionary<string>(source);
|
||||
var viewData2 = new ViewDataDictionary<string>(source, model: null);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(viewData1.ModelMetadata);
|
||||
Assert.Equal(expectedType, viewData1.ModelMetadata.ModelType);
|
||||
Assert.Equal(expectedType, viewData1.ModelMetadata.RealModelType);
|
||||
|
||||
Assert.NotNull(viewData2.ModelMetadata);
|
||||
Assert.Equal(expectedType, viewData2.ModelMetadata.ModelType);
|
||||
Assert.Equal(expectedType, viewData2.ModelMetadata.RealModelType);
|
||||
}
|
||||
|
||||
public static TheoryData<object, string, object> Eval_EvaluatesExpressionsData
|
||||
{
|
||||
get
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
var actionContext = new ActionContext(routeContext, new ActionDescriptor());
|
||||
var viewContext = new ViewContext(actionContext,
|
||||
Mock.Of<IView>(),
|
||||
new ViewDataDictionary(Mock.Of<IModelMetadataProvider>()),
|
||||
new ViewDataDictionary(new EmptyModelMetadataProvider()),
|
||||
TextWriter.Null);
|
||||
|
||||
// Act
|
||||
|
|
@ -68,7 +68,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
var actionContext = new ActionContext(routeContext, new ActionDescriptor());
|
||||
var viewContext = new ViewContext(actionContext,
|
||||
Mock.Of<IView>(),
|
||||
new ViewDataDictionary(Mock.Of<IModelMetadataProvider>()),
|
||||
new ViewDataDictionary(new EmptyModelMetadataProvider()),
|
||||
TextWriter.Null);
|
||||
|
||||
// Act and Assert
|
||||
|
|
@ -101,7 +101,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
.Returns(serviceProvider.Object);
|
||||
var routeContext = new RouteContext(httpContext.Object);
|
||||
var actionContext = new ActionContext(routeContext, new ActionDescriptor());
|
||||
var viewData = new ViewDataDictionary(Mock.Of<IModelMetadataProvider>())
|
||||
var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider())
|
||||
{
|
||||
Model = new MyModel()
|
||||
};
|
||||
|
|
@ -136,7 +136,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
.Returns(serviceProvider.Object);
|
||||
var routeContext = new RouteContext(httpContext.Object);
|
||||
var actionContext = new ActionContext(routeContext, new ActionDescriptor());
|
||||
var viewData = new ViewDataDictionary<MyModel>(Mock.Of<IModelMetadataProvider>())
|
||||
var viewData = new ViewDataDictionary<MyModel>(new EmptyModelMetadataProvider())
|
||||
{
|
||||
Model = new MyModel()
|
||||
};
|
||||
|
|
@ -171,7 +171,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
.Returns(serviceProvider.Object);
|
||||
var routeContext = new RouteContext(httpContext.Object);
|
||||
var actionContext = new ActionContext(routeContext, new ActionDescriptor());
|
||||
var viewData = new ViewDataDictionary(Mock.Of<IModelMetadataProvider>());
|
||||
var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider());
|
||||
var viewContext = new ViewContext(actionContext,
|
||||
Mock.Of<IView>(),
|
||||
viewData,
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
.Returns(serviceProvider.Object);
|
||||
var routeContext = new RouteContext(httpContext.Object);
|
||||
var actionContext = new ActionContext(routeContext, new ActionDescriptor());
|
||||
var viewData = new ViewDataDictionary(Mock.Of<IModelMetadataProvider>());
|
||||
var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider());
|
||||
var viewContext = new ViewContext(actionContext,
|
||||
Mock.Of<IView>(),
|
||||
viewData,
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ namespace Microsoft.AspNet.Mvc.Razor
|
|||
public async Task RenderAsync_AsPartial_ActivatesViews_WithThePassedInViewContext()
|
||||
{
|
||||
// Arrange
|
||||
var viewData = new ViewDataDictionary(Mock.Of<IModelMetadataProvider>());
|
||||
var viewData = new ViewDataDictionary(new EmptyModelMetadataProvider());
|
||||
var page = new TestableRazorPage(v =>
|
||||
{
|
||||
// viewData is assigned to ViewContext by the activator
|
||||
|
|
@ -867,7 +867,7 @@ section-content-2";
|
|||
return new ViewContext(
|
||||
actionContext,
|
||||
view,
|
||||
new ViewDataDictionary(Mock.Of<IModelMetadataProvider>()),
|
||||
new ViewDataDictionary(new EmptyModelMetadataProvider()),
|
||||
new StringWriter());
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue