From 5420b9d38289e2a973a4489f9a8dc4b7b934fc77 Mon Sep 17 00:00:00 2001 From: Doug Bunting Date: Mon, 27 Oct 2014 09:00:48 -0700 Subject: [PATCH] More `ViewDataDictionary` tests - separate and extend `ViewDataDictionary` tests --- .../ViewDataDictionaryOfTModelTest.cs | 331 ++++++++++++++++++ .../ViewDataDictionaryTest.cs | 89 +++-- 2 files changed, 386 insertions(+), 34 deletions(-) create mode 100644 test/Microsoft.AspNet.Mvc.Core.Test/ViewDataDictionaryOfTModelTest.cs diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ViewDataDictionaryOfTModelTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ViewDataDictionaryOfTModelTest.cs new file mode 100644 index 0000000000..3d3904be56 --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.Core.Test/ViewDataDictionaryOfTModelTest.cs @@ -0,0 +1,331 @@ +// 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 System; +using Microsoft.AspNet.Mvc.ModelBinding; +using Xunit; + +namespace Microsoft.AspNet.Mvc.Core +{ + public class ViewDataDictionaryOfTModelTest + { + [Fact] + public void Constructor_InitalizesMembers() + { + // Arrange + var metadataProvider = new EmptyModelMetadataProvider(); + var modelState = new ModelStateDictionary(); + + // Act + var viewData = new ViewDataDictionary(metadataProvider, modelState); + + // Assert + Assert.Same(modelState, viewData.ModelState); + Assert.NotNull(viewData.TemplateInfo); + Assert.Null(viewData.Model); + Assert.NotNull(viewData.ModelMetadata); + Assert.Equal(0, viewData.Count); + } + + [Fact] + public void CopyConstructors_InitalizeModelAndModelMetadataBasedOnSource() + { + // Arrange + var metadataProvider = new EmptyModelMetadataProvider(); + var model = new TestModel(); + var source = new ViewDataDictionary(metadataProvider) + { + Model = model + }; + source["foo"] = "bar"; + source.TemplateInfo.HtmlFieldPrefix = "prefix"; + + // Act + var viewData1 = new ViewDataDictionary(source); + var viewData2 = new ViewDataDictionary(source); + + // Assert + Assert.NotNull(viewData1.ModelState); + Assert.NotNull(viewData1.TemplateInfo); + Assert.Equal("prefix", viewData1.TemplateInfo.HtmlFieldPrefix); + Assert.NotSame(source.TemplateInfo, viewData1.TemplateInfo); + Assert.Same(model, viewData1.Model); + Assert.NotNull(viewData1.ModelMetadata); + Assert.Equal(typeof(TestModel), viewData1.ModelMetadata.ModelType); + Assert.Same(source.ModelMetadata, viewData1.ModelMetadata); + Assert.Equal(source.Count, viewData1.Count); + Assert.Equal("bar", viewData1["foo"]); + Assert.IsType>(viewData1.Data); + + Assert.NotNull(viewData2.ModelState); + Assert.NotNull(viewData2.TemplateInfo); + Assert.Equal("prefix", viewData2.TemplateInfo.HtmlFieldPrefix); + Assert.NotSame(source.TemplateInfo, viewData2.TemplateInfo); + Assert.Same(model, viewData2.Model); + Assert.NotNull(viewData2.ModelMetadata); + Assert.Equal(typeof(TestModel), viewData2.ModelMetadata.ModelType); + Assert.Same(source.ModelMetadata, viewData2.ModelMetadata); + Assert.Equal(source.Count, viewData2.Count); + Assert.Equal("bar", viewData2["foo"]); + Assert.IsType>(viewData2.Data); + } + + [Fact] + public void CopyConstructors_InitalizeModelAndModelMetadataBasedOnSource_NullModel() + { + // Arrange + var metadataProvider = new EmptyModelMetadataProvider(); + var source = new ViewDataDictionary(metadataProvider); + source["foo"] = "bar"; + source.TemplateInfo.HtmlFieldPrefix = "prefix"; + + // Act + var viewData1 = new ViewDataDictionary(source); + var viewData2 = new ViewDataDictionary(source); + + // Assert + Assert.NotNull(viewData1.ModelState); + Assert.NotNull(viewData1.TemplateInfo); + Assert.Equal("prefix", viewData1.TemplateInfo.HtmlFieldPrefix); + Assert.NotSame(source.TemplateInfo, viewData1.TemplateInfo); + Assert.Null(viewData1.Model); + Assert.NotNull(viewData1.ModelMetadata); + Assert.Equal(typeof(TestModel), viewData1.ModelMetadata.ModelType); + Assert.Same(source.ModelMetadata, viewData1.ModelMetadata); + Assert.Equal(source.Count, viewData1.Count); + Assert.Equal("bar", viewData1["foo"]); + Assert.IsType>(viewData1.Data); + + Assert.NotNull(viewData2.ModelState); + Assert.NotNull(viewData2.TemplateInfo); + Assert.Equal("prefix", viewData2.TemplateInfo.HtmlFieldPrefix); + Assert.NotSame(source.TemplateInfo, viewData2.TemplateInfo); + Assert.Null(viewData2.Model); + Assert.NotNull(viewData2.ModelMetadata); + Assert.Equal(typeof(TestModel), viewData2.ModelMetadata.ModelType); + Assert.Same(source.ModelMetadata, viewData2.ModelMetadata); + Assert.Equal(source.Count, viewData2.Count); + Assert.Equal("bar", viewData2["foo"]); + Assert.IsType>(viewData2.Data); + } + + [Fact] + public void CopyConstructors_InitalizeModelAndModelMetadataBasedOnSource_ModelOfSubclass() + { + // Arrange + var metadataProvider = new EmptyModelMetadataProvider(); + var model = new SupremeTestModel(); + var source = new ViewDataDictionary(metadataProvider) + { + Model = model, + }; + source["foo"] = "bar"; + source.TemplateInfo.HtmlFieldPrefix = "prefix"; + + // Act + var viewData1 = new ViewDataDictionary(source); + var viewData2 = new ViewDataDictionary(source); + + // Assert + Assert.NotNull(viewData1.ModelState); + Assert.NotNull(viewData1.TemplateInfo); + Assert.Equal("prefix", viewData1.TemplateInfo.HtmlFieldPrefix); + Assert.NotSame(source.TemplateInfo, viewData1.TemplateInfo); + Assert.Same(model, viewData1.Model); + Assert.NotNull(viewData1.ModelMetadata); + Assert.Equal(typeof(SupremeTestModel), viewData1.ModelMetadata.ModelType); + Assert.Same(source.ModelMetadata, viewData1.ModelMetadata); + Assert.Equal(source.Count, viewData1.Count); + Assert.Equal("bar", viewData1["foo"]); + Assert.IsType>(viewData1.Data); + + Assert.NotNull(viewData2.ModelState); + Assert.NotNull(viewData2.TemplateInfo); + Assert.Equal("prefix", viewData2.TemplateInfo.HtmlFieldPrefix); + Assert.NotSame(source.TemplateInfo, viewData2.TemplateInfo); + Assert.Same(model, viewData2.Model); + Assert.NotNull(viewData2.ModelMetadata); + Assert.Equal(typeof(SupremeTestModel), viewData2.ModelMetadata.ModelType); + Assert.Same(source.ModelMetadata, viewData2.ModelMetadata); + Assert.Equal(source.Count, viewData2.Count); + Assert.Equal("bar", viewData2["foo"]); + Assert.IsType>(viewData2.Data); + } + + [Fact] + public void CopyConstructor_DoesNotThrowOnNullModel_WithValueTypeTModel() + { + // Arrange + var metadataProvider = new EmptyModelMetadataProvider(); + var source = new ViewDataDictionary(metadataProvider); + source["key1"] = "value1"; + source.TemplateInfo.HtmlFieldPrefix = "prefix"; + + // Act + var viewData = new ViewDataDictionary(source, model: null); + + // Assert + Assert.NotNull(viewData.ModelState); + Assert.NotNull(viewData.TemplateInfo); + Assert.Equal("prefix", viewData.TemplateInfo.HtmlFieldPrefix); + Assert.NotSame(source.TemplateInfo, viewData.TemplateInfo); + Assert.Equal(0, viewData.Model); + Assert.NotNull(viewData.ModelMetadata); + Assert.Equal(typeof(int), viewData.ModelMetadata.ModelType); + Assert.NotSame(source.ModelMetadata, viewData.ModelMetadata); + Assert.Equal(source.Count, viewData.Count); + Assert.Equal("value1", viewData["key1"]); + Assert.IsType>(viewData.Data); + } + + [Fact] + public void CopyConstructors_OverrideSourceMetadata_IfDeclaredTypeChanged() + { + // Arrange + var expectedType = typeof(string); + var metadataProvider = new EmptyModelMetadataProvider(); + var source = new ViewDataDictionary(metadataProvider); + + // Act + var viewData1 = new ViewDataDictionary(source); + var viewData2 = new ViewDataDictionary(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); + } + + [Fact] + public void CopyConstructors_ThrowInvalidOperation_IfModelIncompatible() + { + // Arrange + var expectedMessage = "The model item passed into the ViewDataDictionary is of type 'System.Int32', " + + "but this ViewDataDictionary instance requires a model item of type 'System.String'."; + var metadataProvider = new EmptyModelMetadataProvider(); + var source = new ViewDataDictionary(metadataProvider) + { + Model = 23, + }; + + // Act & Assert + var exception = Assert.Throws(() => new ViewDataDictionary(source)); + Assert.Equal(expectedMessage, exception.Message); + + exception = Assert.Throws(() => new ViewDataDictionary(source, model: 24)); + Assert.Equal(expectedMessage, exception.Message); + } + + [Fact] + public void ModelSetters_AcceptCompatibleValue() + { + // Arrange + var metadataProvider = new EmptyModelMetadataProvider(); + var viewData1 = new ViewDataDictionary(metadataProvider); + var viewData2 = new ViewDataDictionary(viewData1); + var viewData3 = new ViewDataDictionary(viewData2, model: null); + var viewData4 = new ViewDataDictionary(viewData3); + + // Act + viewData1.Model = 23; + viewData2.Model = 24; + viewData3.Model = 25; + viewData4.Model = 26; + + // Assert + Assert.Equal(23, viewData1.Model); + Assert.Equal(24, viewData2.Model); + Assert.Equal(25, viewData3.Model); + Assert.Equal(26, viewData4.Model); + } + + [Fact] + public void ModelSetters_AcceptNullValue() + { + // Arrange + var metadataProvider = new EmptyModelMetadataProvider(); + var viewData1 = new ViewDataDictionary(metadataProvider); + var viewData2 = new ViewDataDictionary(viewData1); + var viewData3 = new ViewDataDictionary(viewData2, model: null); + var viewData4 = new ViewDataDictionary(viewData3); + + // Act + viewData1.Model = null; + viewData2.Model = null; + viewData3.Model = null; + viewData4.Model = null; + + // Assert + Assert.Null(viewData1.Model); + Assert.Null(viewData2.Model); + Assert.Null(viewData3.Model); + Assert.Null(viewData4.Model); + } + + [Fact] + public void ModelSetters_ThrowInvalidOperation_IfModelIncompatible() + { + // Arrange + var expectedMessage = "The model item passed into the ViewDataDictionary is of type 'System.Int32', " + + "but this ViewDataDictionary instance requires a model item of type 'System.String'."; + var metadataProvider = new EmptyModelMetadataProvider(); + var viewData1 = (ViewDataDictionary)new ViewDataDictionary(metadataProvider); + var viewData2 = (ViewDataDictionary)new ViewDataDictionary(viewData1); + var viewData3 = (ViewDataDictionary)new ViewDataDictionary(viewData2, model: null); + var viewData4 = new ViewDataDictionary(viewData3); + + // Act & Assert + var exception = Assert.Throws(() => viewData1.Model = 23); + Assert.Equal(expectedMessage, exception.Message); + + exception = Assert.Throws(() => viewData2.Model = 24); + Assert.Equal(expectedMessage, exception.Message); + + exception = Assert.Throws(() => viewData3.Model = 25); + Assert.Equal(expectedMessage, exception.Message); + + // Non-generic ViewDataDictionary maintains type restrictions of source with 1-parameter constructor. + exception = Assert.Throws(() => viewData4.Model = 26); + Assert.Equal(expectedMessage, exception.Message); + } + + [Fact] + public void ModelSetters_ThrowInvalidOperation_IfModelNullAndTModelNonNullable() + { + // Arrange + var expectedMessage = "The model item passed is null, " + + "but this ViewDataDictionary instance requires a non-null model item of type 'System.Int32'."; + var metadataProvider = new EmptyModelMetadataProvider(); + var viewData1 = (ViewDataDictionary)new ViewDataDictionary(metadataProvider); + var viewData2 = (ViewDataDictionary)new ViewDataDictionary(viewData1); + var viewData3 = (ViewDataDictionary)new ViewDataDictionary(viewData2, model: null); + var viewData4 = new ViewDataDictionary(viewData3); + + // Act & Assert + var exception = Assert.Throws(() => viewData1.Model = null); + Assert.Equal(expectedMessage, exception.Message); + + exception = Assert.Throws(() => viewData2.Model = null); + Assert.Equal(expectedMessage, exception.Message); + + exception = Assert.Throws(() => viewData3.Model = null); + Assert.Equal(expectedMessage, exception.Message); + + // Non-generic ViewDataDictionary maintains type restrictions of source with 1-parameter constructor. + exception = Assert.Throws(() => viewData4.Model = null); + Assert.Equal(expectedMessage, exception.Message); + } + + private class TestModel + { + } + + private class SupremeTestModel : TestModel + { + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ViewDataDictionaryTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ViewDataDictionaryTest.cs index 61cb0fef38..e39a5cbc95 100644 --- a/test/Microsoft.AspNet.Mvc.Core.Test/ViewDataDictionaryTest.cs +++ b/test/Microsoft.AspNet.Mvc.Core.Test/ViewDataDictionaryTest.cs @@ -84,6 +84,7 @@ namespace Microsoft.AspNet.Mvc.Core Model = model }; source["foo"] = "bar"; + source.TemplateInfo.HtmlFieldPrefix = "prefix"; // Act var viewData = new ViewDataDictionary(source); @@ -91,16 +92,19 @@ namespace Microsoft.AspNet.Mvc.Core // Assert Assert.NotNull(viewData.ModelState); Assert.NotNull(viewData.TemplateInfo); + Assert.Equal("prefix", viewData.TemplateInfo.HtmlFieldPrefix); Assert.NotSame(source.TemplateInfo, viewData.TemplateInfo); Assert.Same(model, viewData.Model); Assert.NotNull(viewData.ModelMetadata); Assert.Equal(typeof(TestModel), viewData.ModelMetadata.ModelType); + Assert.Same(source.ModelMetadata, viewData.ModelMetadata); + Assert.Equal(source.Count, viewData.Count); Assert.Equal("bar", viewData["foo"]); Assert.IsType>(viewData.Data); } [Fact] - public void CopyConstructorUsesPassedInModel() + public void CopyConstructorUsesPassedInModel_DifferentModels() { // Arrange var metadataProvider = new EmptyModelMetadataProvider(); @@ -110,6 +114,7 @@ namespace Microsoft.AspNet.Mvc.Core Model = "string model" }; source["key1"] = "value1"; + source.TemplateInfo.HtmlFieldPrefix = "prefix"; // Act var viewData = new ViewDataDictionary(source, model); @@ -117,9 +122,41 @@ namespace Microsoft.AspNet.Mvc.Core // Assert Assert.NotNull(viewData.ModelState); Assert.NotNull(viewData.TemplateInfo); + Assert.Equal("prefix", viewData.TemplateInfo.HtmlFieldPrefix); + Assert.NotSame(source.TemplateInfo, viewData.TemplateInfo); Assert.Same(model, viewData.Model); Assert.NotNull(viewData.ModelMetadata); Assert.Equal(typeof(TestModel), viewData.ModelMetadata.ModelType); + Assert.NotSame(source.ModelMetadata, viewData.ModelMetadata); + Assert.Equal(source.Count, viewData.Count); + Assert.Equal("value1", viewData["key1"]); + Assert.IsType>(viewData.Data); + } + + [Fact] + public void CopyConstructorUsesPassedInModel_SameModel() + { + // Arrange + var metadataProvider = new EmptyModelMetadataProvider(); + var model = new TestModel(); + var source = new ViewDataDictionary(metadataProvider) + { + Model = model + }; + source["key1"] = "value1"; + + // Act + var viewData = new ViewDataDictionary(source, model); + + // Assert + Assert.NotNull(viewData.ModelState); + Assert.NotNull(viewData.TemplateInfo); + Assert.NotSame(source.TemplateInfo, viewData.TemplateInfo); + Assert.Same(model, viewData.Model); + Assert.NotNull(viewData.ModelMetadata); + Assert.Equal(typeof(TestModel), viewData.ModelMetadata.ModelType); + Assert.Same(source.ModelMetadata, viewData.ModelMetadata); + Assert.Equal(source.Count, viewData.Count); Assert.Equal("value1", viewData["key1"]); Assert.IsType>(viewData.Data); } @@ -133,33 +170,17 @@ namespace Microsoft.AspNet.Mvc.Core source["key1"] = "value1"; // Act - var viewData = new ViewDataDictionary(source, null); + var viewData = new ViewDataDictionary(source, model: null); // Assert Assert.NotNull(viewData.ModelState); Assert.NotNull(viewData.TemplateInfo); + Assert.NotSame(source.TemplateInfo, viewData.TemplateInfo); Assert.Null(viewData.Model); Assert.NotNull(viewData.ModelMetadata); - Assert.Equal("value1", viewData["key1"]); - Assert.IsType>(viewData.Data); - } - - [Fact] - public void CopyConstructorDoesNotThrowOnNullModel_WithValueTypeTModel() - { - // Arrange - var metadataProvider = new EmptyModelMetadataProvider(); - var source = new ViewDataDictionary(metadataProvider); - source["key1"] = "value1"; - - // Act - var viewData = new ViewDataDictionary(source, model: null); - - // Assert - Assert.NotNull(viewData.ModelState); - Assert.NotNull(viewData.TemplateInfo); - Assert.Equal(0, viewData.Model); - Assert.NotNull(viewData.ModelMetadata); + Assert.Equal(typeof(object), viewData.ModelMetadata.ModelType); + Assert.Same(source.ModelMetadata, viewData.ModelMetadata); + Assert.Equal(source.Count, viewData.Count); Assert.Equal("value1", viewData["key1"]); Assert.IsType>(viewData.Data); } @@ -257,25 +278,25 @@ namespace Microsoft.AspNet.Mvc.Core } [Fact] - public void CopyConstructors_OverrideSourceMetadata_IfDeclaredTypeChanged() + public void ModelSetter_UpdatesModelMetadata() { // Arrange - var expectedType = typeof(string); var metadataProvider = new EmptyModelMetadataProvider(); - var source = new ViewDataDictionary(metadataProvider); + var viewData = new ViewDataDictionary(metadataProvider) + { + Model = "same-string", + }; + var originalMetadata = viewData.ModelMetadata; // Act - var viewData1 = new ViewDataDictionary(source); - var viewData2 = new ViewDataDictionary(source, model: null); + viewData.Model = "same-string"; // 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); + Assert.NotNull(viewData.ModelMetadata); + Assert.Equal("same-string", viewData.Model); + Assert.Equal("same-string", viewData.ModelMetadata.Model); + Assert.Same(originalMetadata.ModelType, viewData.ModelMetadata.ModelType); + Assert.NotSame(originalMetadata, viewData.ModelMetadata); } public static TheoryData Eval_EvaluatesExpressionsData