// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. using System.Linq; using System.Web.Routing; using System.Web.TestUtil; using Microsoft.Web.UnitTestUtil; using Moq; using Xunit; using Assert = Microsoft.TestCommon.AssertEx; namespace System.Web.Mvc.Test { public class ControllerBaseTest { [Fact] public void ExecuteCallsControllerBaseExecute() { // Arrange RequestContext requestContext = new RequestContext(HttpContextHelpers.GetMockHttpContext().Object, new RouteData()); Mock mockController = new Mock() { CallBase = true }; mockController.Setup(c => c.PublicInitialize(requestContext)).Verifiable(); mockController.Setup(c => c.PublicExecuteCore()).Verifiable(); IController controller = mockController.Object; // Act controller.Execute(requestContext); // Assert mockController.Verify(); } [Fact] public void ExecuteThrowsIfCalledTwice() { // Arrange EmptyControllerBase controller = new EmptyControllerBase(); RequestContext requestContext = new RequestContext(HttpContextHelpers.GetMockHttpContext().Object, new RouteData()); // Act ((IController)controller).Execute(requestContext); // first call Assert.Throws( delegate { ((IController)controller).Execute(requestContext); // second call }, @"A single instance of controller 'System.Web.Mvc.Test.ControllerBaseTest+EmptyControllerBase' cannot be used to handle multiple requests. If a custom controller factory is in use, make sure that it creates a new instance of the controller for each request."); // Assert Assert.Equal(1, controller.NumTimesExecuteCoreCalled); } [Fact] public void ExecuteThrowsIfRequestContextIsNull() { // Arrange IController controller = new ControllerBaseHelper(); // Act & Assert Assert.ThrowsArgumentNull( delegate { controller.Execute(null); }, "requestContext"); } [Fact] public void ExecuteThrowsIfRequestContextHttpContextIsNull() { //Arrange IController controller = new ControllerBaseHelper(); //Act & Assert Assert.Throws( delegate { controller.Execute(new Mock().Object); }, "Cannot execute Controller with a null HttpContext.\r\nParameter name: requestContext"); } [Fact] public void InitializeSetsControllerContext() { // Arrange ControllerBaseHelper helper = new ControllerBaseHelper(); RequestContext requestContext = new RequestContext(new Mock().Object, new RouteData()); // Act helper.PublicInitialize(requestContext); // Assert Assert.Same(requestContext.HttpContext, helper.ControllerContext.HttpContext); Assert.Same(requestContext.RouteData, helper.ControllerContext.RouteData); Assert.Same(helper, helper.ControllerContext.Controller); } [Fact] public void TempDataProperty() { // Arrange ControllerBase controller = new ControllerBaseHelper(); // Act & Assert MemberHelper.TestPropertyWithDefaultInstance(controller, "TempData", new TempDataDictionary()); } [Fact] public void TempDataReturnsParentTempDataWhenInChildRequest() { // Arrange TempDataDictionary tempData = new TempDataDictionary(); ViewContext viewContext = new ViewContext { TempData = tempData }; RouteData routeData = new RouteData(); routeData.DataTokens[ControllerContext.ParentActionViewContextToken] = viewContext; RequestContext requestContext = new RequestContext(new Mock().Object, routeData); ControllerBaseHelper controller = new ControllerBaseHelper(); controller.PublicInitialize(requestContext); // Act TempDataDictionary result = controller.TempData; // Assert Assert.Same(result, tempData); } [Fact] public void ValidateRequestProperty() { // Arrange ControllerBase controller = new ControllerBaseHelper(); // Act & assert MemberHelper.TestBooleanProperty(controller, "ValidateRequest", true /* initialValue */, false /* testDefaultValue */); } [Fact] public void ValueProviderProperty() { // Arrange ControllerBase controller = new ControllerBaseHelper(); IValueProvider valueProvider = new SimpleValueProvider(); // Act & assert ValueProviderFactory[] originalFactories = ValueProviderFactories.Factories.ToArray(); try { ValueProviderFactories.Factories.Clear(); MemberHelper.TestPropertyWithDefaultInstance(controller, "ValueProvider", valueProvider); } finally { foreach (ValueProviderFactory factory in originalFactories) { ValueProviderFactories.Factories.Add(factory); } } } [Fact] public void ViewDataProperty() { // Arrange ControllerBase controller = new ControllerBaseHelper(); // Act & Assert MemberHelper.TestPropertyWithDefaultInstance(controller, "ViewData", new ViewDataDictionary()); } [Fact] public void ViewBagProperty_ReflectsViewData() { // Arrange ControllerBase controller = new ControllerBaseHelper(); controller.ViewData["A"] = 1; // Act & Assert Assert.NotNull(controller.ViewBag); Assert.Equal(1, controller.ViewBag.A); } [Fact] public void ViewBagProperty_ReflectsNewViewDataInstance() { // Arrange ControllerBase controller = new ControllerBaseHelper(); controller.ViewData["A"] = 1; controller.ViewData = new ViewDataDictionary() { { "A", "bar" } }; // Act & Assert Assert.Equal("bar", controller.ViewBag.A); } [Fact] public void ViewBag_PropagatesChangesToViewData() { // Arrange ControllerBase controller = new ControllerBaseHelper(); controller.ViewData["A"] = 1; // Act controller.ViewBag.A = "foo"; controller.ViewBag.B = 2; // Assert Assert.Equal("foo", controller.ViewData["A"]); Assert.Equal(2, controller.ViewData["B"]); } public class ControllerBaseHelper : ControllerBase { protected override void Initialize(RequestContext requestContext) { PublicInitialize(requestContext); } public virtual void PublicInitialize(RequestContext requestContext) { base.Initialize(requestContext); } protected override void ExecuteCore() { PublicExecuteCore(); } public virtual void PublicExecuteCore() { throw new NotImplementedException(); } } private class EmptyControllerBase : ControllerBase { public int NumTimesExecuteCoreCalled = 0; protected override void ExecuteCore() { NumTimesExecuteCoreCalled++; } } } }