Test Example in System.Web.Mvc
Because the mvc project and test project are seperate, we need the test project to see the internal member in System.Web.Mvc project, so there is a attribute in the mvc project.
[assembly: InternalsVisibleTo("System.Web.Mvc.Test")]
The effort to make the project testable of the mvc project is very obvious. For example, to make DefaultControllerFactory testable, the class has a property setter, so that test project can inject mocking object.
DefaultControllerFactory factory = new DefaultControllerFactory(); MockBuildManager buildManagerMock = new MockBuildManager(new Assembly[] { }); ControllerTypeCache controllerTypeCache = new ControllerTypeCache(); factory.BuildManager = buildManagerMock; factory.ControllerTypeCache = controllerTypeCache; // Act Type controllerType = factory.GetControllerType("sometype"); // Assert Assert.IsNull(controllerType, "Shouldn't have found a controller type."); Assert.AreEqual<int>(0, controllerTypeCache.Count, "Cache should be empty."); //member of DefaultControllerFactory internal IBuildManager BuildManager { get { if (_buildManager == null) { _buildManager = new BuildManagerWrapper(); } return _buildManager; } set { _buildManager = value; } } internal ControllerBuilder ControllerBuilder { get { return _controllerBuilder ?? ControllerBuilder.Current; } set { _controllerBuilder = value; } }
Another example is as follow. Even we need to increase performance of the by using staticControllerTypeCase, we still allow test project to inject an _instanceControllerTypeCase for testing.
//member of DefaultControllerFactory internal ControllerTypeCache ControllerTypeCache { get { return _instanceControllerTypeCache ?? _staticControllerTypeCache; } set { _instanceControllerTypeCache = value; } } //member of ControllerContext //RouteData can be mocked. public virtual RouteData RouteData { get { if (_routeData == null) { _routeData = (_requestContext != null) ? _requestContext.RouteData : new RouteData(); } return _routeData; } set { _routeData = value; } }