Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

769 lines
33 KiB
C#

// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Reflection;
using System.Web.Routing;
using System.Web.SessionState;
using Moq;
using Xunit;
using Xunit.Extensions;
using Assert = Microsoft.TestCommon.AssertEx;
namespace System.Web.Mvc.Test
{
[CLSCompliant(false)]
public class DefaultControllerFactoryTest
{
static DefaultControllerFactoryTest()
{
MvcTestHelper.CreateMvcAssemblies();
}
[Fact]
public void CreateAmbiguousControllerException_RouteWithoutUrl()
{
// Arrange
RouteBase route = new Mock<RouteBase>().Object;
Type[] matchingTypes = new Type[]
{
typeof(object),
typeof(string)
};
// Act
InvalidOperationException exception = DefaultControllerFactory.CreateAmbiguousControllerException(route, "Foo", matchingTypes);
// Assert
Assert.Equal(@"Multiple types were found that match the controller named 'Foo'. This can happen if the route that services this request does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.
The request for 'Foo' has found the following matching controllers:
System.Object
System.String", exception.Message);
}
[Fact]
public void CreateAmbiguousControllerException_RouteWithUrl()
{
// Arrange
RouteBase route = new Route("{controller}/blah", new Mock<IRouteHandler>().Object);
Type[] matchingTypes = new Type[]
{
typeof(object),
typeof(string)
};
// Act
InvalidOperationException exception = DefaultControllerFactory.CreateAmbiguousControllerException(route, "Foo", matchingTypes);
// Assert
Assert.Equal(@"Multiple types were found that match the controller named 'Foo'. This can happen if the route that services this request ('{controller}/blah') does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.
The request for 'Foo' has found the following matching controllers:
System.Object
System.String", exception.Message);
}
[Fact]
public void CreateControllerWithNullContextThrows()
{
// Arrange
DefaultControllerFactory factory = new DefaultControllerFactory();
// Act
Assert.ThrowsArgumentNull(
delegate
{
((IControllerFactory)factory).CreateController(
null,
"foo");
},
"requestContext");
}
[Fact]
public void CreateControllerWithEmptyControllerNameThrows()
{
// Arrange
DefaultControllerFactory factory = new DefaultControllerFactory();
// Act
Assert.Throws<ArgumentException>(
delegate
{
((IControllerFactory)factory).CreateController(
new RequestContext(new Mock<HttpContextBase>().Object, new RouteData()),
String.Empty);
},
"Value cannot be null or empty.\r\nParameter name: controllerName");
}
[Fact]
public void CreateControllerReturnsControllerInstance()
{
// Arrange
RequestContext requestContext = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
Mock<DefaultControllerFactory> factoryMock = new Mock<DefaultControllerFactory>();
factoryMock.CallBase = true;
factoryMock.Setup(o => o.GetControllerType(requestContext, "moo")).Returns(typeof(DummyController));
// Act
IController controller = ((IControllerFactory)factoryMock.Object).CreateController(requestContext, "moo");
// Assert
Assert.IsType<DummyController>(controller);
}
[Fact]
public void CreateControllerCanReturnNull()
{
// Arrange
RequestContext requestContext = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
Mock<DefaultControllerFactory> factoryMock = new Mock<DefaultControllerFactory>();
factoryMock.Setup(o => o.GetControllerType(requestContext, "moo")).Returns(typeof(DummyController));
factoryMock.Setup(o => o.GetControllerInstance(requestContext, typeof(DummyController))).Returns((ControllerBase)null);
// Act
IController controller = ((IControllerFactory)factoryMock.Object).CreateController(requestContext, "moo");
// Assert
Assert.Null(controller);
}
[Fact]
public void DisposeControllerFactoryWithDisposableController()
{
// Arrange
IControllerFactory factory = new DefaultControllerFactory();
Mock<ControllerBase> mockController = new Mock<ControllerBase>();
Mock<IDisposable> mockDisposable = mockController.As<IDisposable>();
mockDisposable.Setup(d => d.Dispose()).Verifiable();
// Act
factory.ReleaseController(mockController.Object);
// Assert
mockDisposable.Verify();
}
[Fact]
public void GetControllerInstanceThrowsIfControllerTypeIsNull()
{
// Arrange
Mock<HttpContextBase> contextMock = new Mock<HttpContextBase>();
Mock<HttpRequestBase> requestMock = new Mock<HttpRequestBase>();
contextMock.Setup(o => o.Request).Returns(requestMock.Object);
requestMock.Setup(o => o.Path).Returns("somepath");
RequestContext requestContext = new RequestContext(contextMock.Object, new RouteData());
Mock<DefaultControllerFactory> factoryMock = new Mock<DefaultControllerFactory> { CallBase = true };
factoryMock.Setup(o => o.GetControllerType(requestContext, "moo")).Returns((Type)null);
// Act
Assert.ThrowsHttpException(
delegate { ((IControllerFactory)factoryMock.Object).CreateController(requestContext, "moo"); },
"The controller for path 'somepath' was not found or does not implement IController.",
404);
}
[Fact]
public void GetControllerInstanceThrowsIfControllerTypeIsNotControllerBase()
{
// Arrange
RequestContext requestContext = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
DefaultControllerFactory factory = new DefaultControllerFactory();
// Act
Assert.Throws<ArgumentException>(
delegate { factory.GetControllerInstance(requestContext, typeof(int)); },
"The controller type 'System.Int32' must implement IController.\r\nParameter name: controllerType");
}
[Fact]
public void GetControllerInstanceWithBadConstructorThrows()
{
// Arrange
Mock<HttpContextBase> contextMock = new Mock<HttpContextBase>();
RequestContext requestContext = new RequestContext(contextMock.Object, new RouteData());
Mock<DefaultControllerFactory> factoryMock = new Mock<DefaultControllerFactory>();
factoryMock.CallBase = true;
factoryMock.Setup(o => o.GetControllerType(requestContext, "moo")).Returns(typeof(DummyControllerThrows));
// Act
Exception ex = Assert.Throws<InvalidOperationException>(
delegate { ((IControllerFactory)factoryMock.Object).CreateController(requestContext, "moo"); },
"An error occurred when trying to create a controller of type 'System.Web.Mvc.Test.DefaultControllerFactoryTest+DummyControllerThrows'. Make sure that the controller has a parameterless public constructor.");
Assert.Equal("constructor", ex.InnerException.InnerException.Message);
}
[Fact]
public void GetControllerSessionBehaviorGuardClauses()
{
// Arrange
RequestContext requestContext = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
IControllerFactory factory = new DefaultControllerFactory();
// Act & Assert
Assert.ThrowsArgumentNull(
() => factory.GetControllerSessionBehavior(null, "controllerName"),
"requestContext"
);
Assert.ThrowsArgumentNullOrEmpty(
() => factory.GetControllerSessionBehavior(requestContext, null),
"controllerName"
);
Assert.ThrowsArgumentNullOrEmpty(
() => factory.GetControllerSessionBehavior(requestContext, ""),
"controllerName"
);
}
[Fact]
public void GetControllerSessionBehaviorReturnsDefaultForNullControllerType()
{
// Arrange
var factory = new DefaultControllerFactory();
// Act
SessionStateBehavior result = factory.GetControllerSessionBehavior(null, null);
// Assert
Assert.Equal(SessionStateBehavior.Default, result);
}
[Fact]
public void GetControllerSessionBehaviorReturnsDefaultForControllerWithoutAttribute()
{
// Arrange
var factory = new DefaultControllerFactory();
// Act
SessionStateBehavior result = factory.GetControllerSessionBehavior(null, typeof(object));
// Assert
Assert.Equal(SessionStateBehavior.Default, result);
}
[Fact]
public void GetControllerSessionBehaviorReturnsAttributeValueFromController()
{
// Arrange
var factory = new DefaultControllerFactory();
// Act
SessionStateBehavior result = factory.GetControllerSessionBehavior(null, typeof(MyReadOnlyController));
// Assert
Assert.Equal(SessionStateBehavior.ReadOnly, result);
}
[SessionState(SessionStateBehavior.ReadOnly)]
class MyReadOnlyController
{
}
[Fact]
public void GetControllerTypeWithEmptyControllerNameThrows()
{
// Arrange
RequestContext requestContext = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
DefaultControllerFactory factory = new DefaultControllerFactory();
// Act
Assert.Throws<ArgumentException>(
delegate { factory.GetControllerType(requestContext, String.Empty); },
"Value cannot be null or empty.\r\nParameter name: controllerName");
}
[Fact]
public void GetControllerTypeForNoAssemblies()
{
// Arrange
RequestContext requestContext = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
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(requestContext, "sometype");
// Assert
Assert.Null(controllerType);
Assert.Equal(0, controllerTypeCache.Count);
}
[Fact]
public void GetControllerTypeForOneAssembly()
{
// Arrange
RequestContext requestContext = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
DefaultControllerFactory factory = GetDefaultControllerFactory("ns1a.ns1b", "ns2a.ns2b");
MockBuildManager buildManagerMock = new MockBuildManager(new Assembly[] { Assembly.Load("MvcAssembly1") });
ControllerTypeCache controllerTypeCache = new ControllerTypeCache();
factory.BuildManager = buildManagerMock;
factory.ControllerTypeCache = controllerTypeCache;
// Act
Type c1Type = factory.GetControllerType(requestContext, "C1");
Type c2Type = factory.GetControllerType(requestContext, "c2");
// Assert
Assembly asm1 = Assembly.Load("MvcAssembly1");
Type verifiedC1 = asm1.GetType("NS1a.NS1b.C1Controller");
Type verifiedC2 = asm1.GetType("NS2a.NS2b.C2Controller");
Assert.Equal(verifiedC1, c1Type);
Assert.Equal(verifiedC2, c2Type);
Assert.Equal(2, controllerTypeCache.Count);
}
[Fact]
public void GetControllerTypeForManyAssemblies()
{
// Arrange
RequestContext requestContext = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
DefaultControllerFactory factory = GetDefaultControllerFactory("ns1a.ns1b", "ns2a.ns2b", "ns3a.ns3b", "ns4a.ns4b");
MockBuildManager buildManagerMock = new MockBuildManager(new Assembly[] { Assembly.Load("MvcAssembly1"), Assembly.Load("MvcAssembly2") });
ControllerTypeCache controllerTypeCache = new ControllerTypeCache();
factory.BuildManager = buildManagerMock;
factory.ControllerTypeCache = controllerTypeCache;
// Act
Type c1Type = factory.GetControllerType(requestContext, "C1");
Type c2Type = factory.GetControllerType(requestContext, "C2");
Type c3Type = factory.GetControllerType(requestContext, "c3"); // lower case
Type c4Type = factory.GetControllerType(requestContext, "c4"); // lower case
// Assert
Assembly asm1 = Assembly.Load("MvcAssembly1");
Type verifiedC1 = asm1.GetType("NS1a.NS1b.C1Controller");
Type verifiedC2 = asm1.GetType("NS2a.NS2b.C2Controller");
Assembly asm2 = Assembly.Load("MvcAssembly2");
Type verifiedC3 = asm2.GetType("NS3a.NS3b.C3Controller");
Type verifiedC4 = asm2.GetType("NS4a.NS4b.C4Controller");
Assert.NotNull(verifiedC1);
Assert.NotNull(verifiedC2);
Assert.NotNull(verifiedC3);
Assert.NotNull(verifiedC4);
Assert.Equal(verifiedC1, c1Type);
Assert.Equal(verifiedC2, c2Type);
Assert.Equal(verifiedC3, c3Type);
Assert.Equal(verifiedC4, c4Type);
Assert.Equal(4, controllerTypeCache.Count);
}
[Fact]
public void GetControllerTypeDoesNotThrowIfSameControllerMatchedMultipleNamespaces()
{
// both namespaces "ns3a" and "ns3a.ns3b" will match a controller type, but it's actually
// the same type. in this case, we shouldn't throw.
// Arrange
RequestContext requestContext = GetRequestContextWithNamespaces("ns3a", "ns3a.ns3b");
requestContext.RouteData.DataTokens["UseNamespaceFallback"] = false;
DefaultControllerFactory factory = GetDefaultControllerFactory("ns1a.ns1b", "ns2a.ns2b");
MockBuildManager buildManagerMock = new MockBuildManager(new Assembly[] { Assembly.Load("MvcAssembly3") });
ControllerTypeCache controllerTypeCache = new ControllerTypeCache();
factory.BuildManager = buildManagerMock;
factory.ControllerTypeCache = controllerTypeCache;
// Act
Type c1Type = factory.GetControllerType(requestContext, "C1");
// Assert
Assembly asm3 = Assembly.Load("MvcAssembly3");
Type verifiedC1 = asm3.GetType("NS3a.NS3b.C1Controller");
Assert.NotNull(verifiedC1);
Assert.Equal(verifiedC1, c1Type);
}
[Fact]
public void GetControllerTypeForAssembliesWithSameTypeNamesInDifferentNamespaces()
{
// Arrange
RequestContext requestContext = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
DefaultControllerFactory factory = GetDefaultControllerFactory("ns1a.ns1b", "ns2a.ns2b");
MockBuildManager buildManagerMock = new MockBuildManager(new Assembly[] { Assembly.Load("MvcAssembly1"), Assembly.Load("MvcAssembly3") });
ControllerTypeCache controllerTypeCache = new ControllerTypeCache();
factory.BuildManager = buildManagerMock;
factory.ControllerTypeCache = controllerTypeCache;
// Act
Type c1Type = factory.GetControllerType(requestContext, "C1");
Type c2Type = factory.GetControllerType(requestContext, "C2");
// Assert
Assembly asm1 = Assembly.Load("MvcAssembly1");
Type verifiedC1 = asm1.GetType("NS1a.NS1b.C1Controller");
Type verifiedC2 = asm1.GetType("NS2a.NS2b.C2Controller");
Assert.NotNull(verifiedC1);
Assert.NotNull(verifiedC2);
Assert.Equal(verifiedC1, c1Type);
Assert.Equal(verifiedC2, c2Type);
Assert.Equal(4, controllerTypeCache.Count);
}
[Fact]
public void GetControllerTypeForAssembliesWithSameTypeNamesInDifferentNamespacesThrowsIfAmbiguous()
{
// Arrange
RequestContext requestContext = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
DefaultControllerFactory factory = GetDefaultControllerFactory("ns1a.ns1b", "ns3a.ns3b");
MockBuildManager buildManagerMock = new MockBuildManager(new Assembly[] { Assembly.Load("MvcAssembly1"), Assembly.Load("MvcAssembly3") });
ControllerTypeCache controllerTypeCache = new ControllerTypeCache();
factory.BuildManager = buildManagerMock;
factory.ControllerTypeCache = controllerTypeCache;
// Act
Assert.Throws<InvalidOperationException>(
delegate { factory.GetControllerType(requestContext, "C1"); },
@"Multiple types were found that match the controller named 'C1'. This can happen if the route that services this request does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.
The request for 'C1' has found the following matching controllers:
NS1a.NS1b.C1Controller
NS3a.NS3b.C1Controller");
// Assert
Assert.Equal(4, controllerTypeCache.Count);
}
[Fact]
public void GetControllerTypeForAssembliesWithSameTypeNamesInSameNamespaceThrows()
{
// Arrange
RequestContext requestContext = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
DefaultControllerFactory factory = GetDefaultControllerFactory("ns1a.ns1b");
MockBuildManager buildManagerMock = new MockBuildManager(new Assembly[] { Assembly.Load("MvcAssembly1"), Assembly.Load("MvcAssembly4") });
ControllerTypeCache controllerTypeCache = new ControllerTypeCache();
factory.BuildManager = buildManagerMock;
factory.ControllerTypeCache = controllerTypeCache;
// Act
Assert.Throws<InvalidOperationException>(
delegate { factory.GetControllerType(requestContext, "C1"); },
@"Multiple types were found that match the controller named 'C1'. This can happen if the route that services this request does not specify namespaces to search for a controller that matches the request. If this is the case, register this route by calling an overload of the 'MapRoute' method that takes a 'namespaces' parameter.
The request for 'C1' has found the following matching controllers:
NS1a.NS1b.C1Controller
NS1a.NS1b.C1Controller");
// Assert
Assert.Equal(4, controllerTypeCache.Count);
}
[Fact]
public void GetControllerTypeSearchesAllNamespacesAsLastResort()
{
// Arrange
RequestContext requestContext = GetRequestContextWithNamespaces("ns3a.ns3b");
DefaultControllerFactory factory = GetDefaultControllerFactory("ns1a.ns1b");
MockBuildManager buildManagerMock = new MockBuildManager(new Assembly[] { Assembly.Load("MvcAssembly1") });
ControllerTypeCache controllerTypeCache = new ControllerTypeCache();
factory.BuildManager = buildManagerMock;
factory.ControllerTypeCache = controllerTypeCache;
// Act
Type c2Type = factory.GetControllerType(requestContext, "C2");
// Assert
Assembly asm1 = Assembly.Load("MvcAssembly1");
Type verifiedC2 = asm1.GetType("NS2a.NS2b.C2Controller");
Assert.NotNull(verifiedC2);
Assert.Equal(verifiedC2, c2Type);
Assert.Equal(2, controllerTypeCache.Count);
}
[Fact]
public void GetControllerTypeSearchesOnlyRouteDefinedNamespacesIfRequested()
{
// Arrange
RequestContext requestContext = GetRequestContextWithNamespaces("ns3a.ns3b");
requestContext.RouteData.DataTokens["UseNamespaceFallback"] = false;
DefaultControllerFactory factory = GetDefaultControllerFactory("ns1a.ns1b", "ns2a.ns2b");
MockBuildManager buildManagerMock = new MockBuildManager(new Assembly[] { Assembly.Load("MvcAssembly1"), Assembly.Load("MvcAssembly3") });
ControllerTypeCache controllerTypeCache = new ControllerTypeCache();
factory.BuildManager = buildManagerMock;
factory.ControllerTypeCache = controllerTypeCache;
// Act
Type c1Type = factory.GetControllerType(requestContext, "C1");
Type c2Type = factory.GetControllerType(requestContext, "C2");
// Assert
Assembly asm3 = Assembly.Load("MvcAssembly3");
Type verifiedC1 = asm3.GetType("NS3a.NS3b.C1Controller");
Assert.NotNull(verifiedC1);
Assert.Equal(verifiedC1, c1Type);
Assert.Null(c2Type);
}
[Fact]
public void GetControllerTypeSearchesRouteDefinedNamespacesBeforeApplicationDefinedNamespaces()
{
// Arrange
RequestContext requestContext = GetRequestContextWithNamespaces("ns3a.ns3b");
DefaultControllerFactory factory = GetDefaultControllerFactory("ns1a.ns1b", "ns2a.ns2b");
MockBuildManager buildManagerMock = new MockBuildManager(new Assembly[] { Assembly.Load("MvcAssembly1"), Assembly.Load("MvcAssembly3") });
ControllerTypeCache controllerTypeCache = new ControllerTypeCache();
factory.BuildManager = buildManagerMock;
factory.ControllerTypeCache = controllerTypeCache;
// Act
Type c1Type = factory.GetControllerType(requestContext, "C1");
Type c2Type = factory.GetControllerType(requestContext, "C2");
// Assert
Assembly asm1 = Assembly.Load("MvcAssembly1");
Type verifiedC2 = asm1.GetType("NS2a.NS2b.C2Controller");
Assembly asm3 = Assembly.Load("MvcAssembly3");
Type verifiedC1 = asm3.GetType("NS3a.NS3b.C1Controller");
Assert.NotNull(verifiedC1);
Assert.NotNull(verifiedC2);
Assert.Equal(verifiedC1, c1Type);
Assert.Equal(verifiedC2, c2Type);
Assert.Equal(4, controllerTypeCache.Count);
}
[Fact]
public void GetControllerTypeThatDoesntExist()
{
// Arrange
RequestContext requestContext = new RequestContext(new Mock<HttpContextBase>().Object, new RouteData());
DefaultControllerFactory factory = GetDefaultControllerFactory("ns1a.ns1b", "ns2a.ns2b", "ns3a.ns3b", "ns4a.ns4b");
MockBuildManager buildManagerMock = new MockBuildManager(new Assembly[] { Assembly.Load("MvcAssembly1"), Assembly.Load("MvcAssembly2"), Assembly.Load("MvcAssembly3"), Assembly.Load("MvcAssembly4") });
ControllerTypeCache controllerTypeCache = new ControllerTypeCache();
factory.BuildManager = buildManagerMock;
factory.ControllerTypeCache = controllerTypeCache;
// Act
Type randomType1 = factory.GetControllerType(requestContext, "Cx");
Type randomType2 = factory.GetControllerType(requestContext, "Cy");
Type randomType3 = factory.GetControllerType(requestContext, "Foo.Bar");
Type randomType4 = factory.GetControllerType(requestContext, "C1Controller");
// Assert
Assert.Null(randomType1);
Assert.Null(randomType2);
Assert.Null(randomType3);
Assert.Null(randomType4);
Assert.Equal(8, controllerTypeCache.Count);
}
[Fact]
public void IsControllerType()
{
// Act
bool isController1 = ControllerTypeCache.IsControllerType(null);
bool isController2 = ControllerTypeCache.IsControllerType(typeof(NonPublicController));
bool isController3 = ControllerTypeCache.IsControllerType(typeof(MisspelledKontroller));
bool isController4 = ControllerTypeCache.IsControllerType(typeof(AbstractController));
bool isController5 = ControllerTypeCache.IsControllerType(typeof(NonIControllerController));
bool isController6 = ControllerTypeCache.IsControllerType(typeof(Goodcontroller));
// Assert
Assert.False(isController1);
Assert.False(isController2);
Assert.False(isController3);
Assert.False(isController4);
Assert.False(isController5);
Assert.True(isController6);
}
[Theory]
[InlineData(null, false)]
[InlineData("", true)]
[InlineData("Dummy", false)]
[InlineData("Dummy.*", true)]
[InlineData("Dummy.Controller.*", false)]
[InlineData("Dummy.Controllers", true)]
[InlineData("Dummy.Controllers.*", true)]
[InlineData("Dummy.Controllers*", false)]
public void IsNamespaceMatch(string testNamespace, bool expectedResult)
{
// Act & Assert
Assert.Equal(expectedResult, ControllerTypeCache.IsNamespaceMatch(testNamespace, "Dummy.Controllers"));
}
[Fact]
public void GetControllerInstanceConsultsSetControllerActivator()
{
//Arrange
Mock<IControllerActivator> activator = new Mock<IControllerActivator>();
DefaultControllerFactory factory = new DefaultControllerFactory(activator.Object);
RequestContext context = new RequestContext();
//Act
factory.GetControllerInstance(context, typeof(Goodcontroller));
//Assert
activator.Verify(l => l.Create(context, typeof(Goodcontroller)));
}
[Fact]
public void GetControllerDelegatesToActivatorResolver()
{
//Arrange
var context = new RequestContext();
var expectedController = new Goodcontroller();
var resolverActivator = new Mock<IControllerActivator>();
resolverActivator.Setup(a => a.Create(context, typeof(Goodcontroller))).Returns(expectedController);
var activatorResolver = new Resolver<IControllerActivator> { Current = resolverActivator.Object };
var factory = new DefaultControllerFactory(null, activatorResolver, null);
//Act
IController returnedController = factory.GetControllerInstance(context, typeof(Goodcontroller));
//Assert
Assert.Same(returnedController, expectedController);
}
[Fact]
public void GetControllerDelegatesToDependencyResolveWhenActivatorResolverIsNull()
{
// Arrange
var context = new RequestContext();
var expectedController = new Goodcontroller();
var dependencyResolver = new Mock<IDependencyResolver>(MockBehavior.Strict);
dependencyResolver.Setup(dr => dr.GetService(typeof(Goodcontroller))).Returns(expectedController);
var factory = new DefaultControllerFactory(null, null, dependencyResolver.Object);
// Act
IController returnedController = factory.GetControllerInstance(context, typeof(Goodcontroller));
// Assert
Assert.Same(returnedController, expectedController);
}
[Fact]
public void GetControllerDelegatesToActivatorCreateInstanceWhenDependencyResolverReturnsNull()
{
// Arrange
var context = new RequestContext();
var dependencyResolver = new Mock<IDependencyResolver>();
var factory = new DefaultControllerFactory(null, null, dependencyResolver.Object);
// Act & Assert
Assert.Throws<InvalidOperationException>(
() => factory.GetControllerInstance(context, typeof(NoParameterlessCtor)),
"An error occurred when trying to create a controller of type 'System.Web.Mvc.Test.DefaultControllerFactoryTest+NoParameterlessCtor'. Make sure that the controller has a parameterless public constructor."
);
}
[Fact]
public void ActivatorResolverAndDependencyResolverAreNeverCalledWhenControllerActivatorIsPassedInConstructor()
{
// Arrange
var context = new RequestContext();
var expectedController = new Goodcontroller();
Mock<IControllerActivator> activator = new Mock<IControllerActivator>();
activator.Setup(a => a.Create(context, typeof(Goodcontroller))).Returns(expectedController);
var resolverActivator = new Mock<IControllerActivator>(MockBehavior.Strict);
var activatorResolver = new Resolver<IControllerActivator> { Current = resolverActivator.Object };
var dependencyResolver = new Mock<IDependencyResolver>(MockBehavior.Strict);
//Act
var factory = new DefaultControllerFactory(activator.Object, activatorResolver, dependencyResolver.Object);
IController returnedController = factory.GetControllerInstance(context, typeof(Goodcontroller));
//Assert
Assert.Same(returnedController, expectedController);
}
class NoParameterlessCtor : IController
{
public NoParameterlessCtor(int x)
{
}
public void Execute(RequestContext requestContext)
{
}
}
private static DefaultControllerFactory GetDefaultControllerFactory(params string[] namespaces)
{
ControllerBuilder builder = new ControllerBuilder();
builder.DefaultNamespaces.UnionWith(namespaces);
return new DefaultControllerFactory() { ControllerBuilder = builder };
}
private static RequestContext GetRequestContextWithNamespaces(params string[] namespaces)
{
RouteData routeData = new RouteData();
routeData.DataTokens["namespaces"] = namespaces;
Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();
RequestContext requestContext = new RequestContext(mockHttpContext.Object, routeData);
return requestContext;
}
private sealed class DummyController : ControllerBase
{
protected override void ExecuteCore()
{
throw new NotImplementedException();
}
}
private sealed class DummyControllerThrows : IController
{
public DummyControllerThrows()
{
throw new Exception("constructor");
}
#region IController Members
void IController.Execute(RequestContext requestContext)
{
throw new NotImplementedException();
}
#endregion
}
public interface IDisposableController : IController, IDisposable
{
}
}
// BAD: type isn't public
internal class NonPublicController : Controller
{
}
// BAD: type doesn't end with 'Controller'
public class MisspelledKontroller : Controller
{
}
// BAD: type is abstract
public abstract class AbstractController : Controller
{
}
// BAD: type doesn't implement IController
public class NonIControllerController
{
}
// GOOD: 'Controller' suffix should be case-insensitive
public class Goodcontroller : Controller
{
}
}