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;
}
}