544 lines
15 KiB
C#
544 lines
15 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
|
using Microsoft.AspNetCore.Mvc.ControllerFeatureProviderControllers;
|
|
using Moq;
|
|
using Xunit;
|
|
|
|
namespace Microsoft.AspNetCore.Mvc.Controllers
|
|
{
|
|
public class ControllerFeatureProviderTest
|
|
{
|
|
[Fact]
|
|
public void UserDefinedClass_DerivedFromController_IsController()
|
|
{
|
|
// Arrange
|
|
var controllerType = typeof(StoreController).GetTypeInfo();
|
|
var manager = GetApplicationPartManager(controllerType);
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
var discovered = Assert.Single(feature.Controllers);
|
|
Assert.Equal(controllerType, discovered);
|
|
}
|
|
|
|
[Fact]
|
|
public void UserDefinedClass_DerivedFromControllerBase_IsController()
|
|
{
|
|
// Arrange
|
|
var controllerType = typeof(ProductsController).GetTypeInfo();
|
|
var manager = GetApplicationPartManager(controllerType);
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
var discovered = Assert.Single(feature.Controllers);
|
|
Assert.Equal(controllerType, discovered);
|
|
}
|
|
|
|
[Fact]
|
|
public void UserDefinedClass_DerivedFromControllerBaseWithoutSuffix_IsController()
|
|
{
|
|
// Arrange
|
|
var controllerType = typeof(Products).GetTypeInfo();
|
|
var manager = GetApplicationPartManager(controllerType);
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
var discovered = Assert.Single(feature.Controllers);
|
|
Assert.Equal(controllerType, discovered);
|
|
}
|
|
|
|
[Fact]
|
|
public void FrameworkControllerClass_IsNotController()
|
|
{
|
|
// Arrange
|
|
var controllerType = typeof(Controller).GetTypeInfo();
|
|
var manager = GetApplicationPartManager(controllerType);
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
Assert.Empty(feature.Controllers);
|
|
}
|
|
|
|
[Fact]
|
|
public void FrameworkBaseControllerClass_IsNotController()
|
|
{
|
|
// Arrange
|
|
var controllerType = typeof(ControllerBase).GetTypeInfo();
|
|
var manager = GetApplicationPartManager(controllerType);
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
Assert.Empty(feature.Controllers);
|
|
}
|
|
|
|
[Fact]
|
|
public void UserDefinedControllerClass_IsNotController()
|
|
{
|
|
// Arrange
|
|
var controllerType = typeof(ControllerFeatureProviderControllers.Controller).GetTypeInfo();
|
|
var manager = GetApplicationPartManager(controllerType);
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
Assert.Empty(feature.Controllers);
|
|
}
|
|
|
|
[Fact]
|
|
public void Interface_IsNotController()
|
|
{
|
|
// Arrange
|
|
var controllerType = typeof(ITestController).GetTypeInfo();
|
|
var manager = GetApplicationPartManager(controllerType);
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
Assert.Empty(feature.Controllers);
|
|
}
|
|
|
|
[Fact]
|
|
public void ValueTypeClass_IsNotController()
|
|
{
|
|
// Arrange
|
|
var controllerType = typeof(int).GetTypeInfo();
|
|
var manager = GetApplicationPartManager(controllerType);
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
Assert.Empty(feature.Controllers);
|
|
}
|
|
|
|
[Fact]
|
|
public void AbstractClass_IsNotController()
|
|
{
|
|
// Arrange
|
|
var controllerType = typeof(AbstractController).GetTypeInfo();
|
|
var manager = GetApplicationPartManager(controllerType);
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
Assert.Empty(feature.Controllers);
|
|
}
|
|
|
|
[Fact]
|
|
public void DerivedAbstractClass_IsController()
|
|
{
|
|
// Arrange
|
|
var controllerType = typeof(DerivedAbstractController).GetTypeInfo();
|
|
var manager = GetApplicationPartManager(controllerType);
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
var discovered = Assert.Single(feature.Controllers);
|
|
Assert.Equal(controllerType, discovered);
|
|
}
|
|
|
|
[Fact]
|
|
public void OpenGenericClass_IsNotController()
|
|
{
|
|
// Arrange
|
|
var controllerType = typeof(OpenGenericController<>).GetTypeInfo();
|
|
var manager = GetApplicationPartManager(controllerType);
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
Assert.Empty(feature.Controllers);
|
|
}
|
|
|
|
[Fact]
|
|
public void WithoutSuffixOrAncestorWithController_IsNotController()
|
|
{
|
|
// Arrange
|
|
var controllerType = typeof(NoSuffixPoco).GetTypeInfo();
|
|
var manager = GetApplicationPartManager(controllerType);
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
Assert.Empty(feature.Controllers);
|
|
}
|
|
|
|
[Fact]
|
|
public void ClosedGenericClass_IsController()
|
|
{
|
|
// Arrange
|
|
var controllerType = typeof(OpenGenericController<string>).GetTypeInfo();
|
|
var manager = GetApplicationPartManager(controllerType);
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
var discovered = Assert.Single(feature.Controllers);
|
|
Assert.Equal(controllerType, discovered);
|
|
}
|
|
|
|
[Fact]
|
|
public void DerivedGenericClass_IsController()
|
|
{
|
|
// Arrange
|
|
var controllerType = typeof(DerivedGenericController).GetTypeInfo();
|
|
var manager = GetApplicationPartManager(controllerType);
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
var discovered = Assert.Single(feature.Controllers);
|
|
Assert.Equal(controllerType, discovered);
|
|
}
|
|
|
|
[Fact]
|
|
public void Poco_WithNamingConvention_IsController()
|
|
{
|
|
// Arrange
|
|
var controllerType = typeof(PocoController).GetTypeInfo();
|
|
var manager = GetApplicationPartManager(controllerType);
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
var discovered = Assert.Single(feature.Controllers);
|
|
Assert.Equal(controllerType, discovered);
|
|
}
|
|
|
|
[Fact]
|
|
public void NoControllerSuffix_IsController()
|
|
{
|
|
// Arrange
|
|
var controllerType = typeof(NoSuffix).GetTypeInfo();
|
|
var manager = GetApplicationPartManager(controllerType);
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
var discovered = Assert.Single(feature.Controllers);
|
|
Assert.Equal(controllerType, discovered);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(typeof(DescendantLevel1))]
|
|
[InlineData(typeof(DescendantLevel2))]
|
|
public void AncestorTypeHasControllerAttribute_IsController(Type type)
|
|
{
|
|
// Arrange
|
|
var manager = GetApplicationPartManager(type.GetTypeInfo());
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
var discovered = Assert.Single(feature.Controllers);
|
|
Assert.Equal(type.GetTypeInfo(), discovered);
|
|
}
|
|
|
|
[Fact]
|
|
public void AncestorTypeDoesNotHaveControllerAttribute_IsNotController()
|
|
{
|
|
// Arrange
|
|
var controllerType = typeof(NoSuffixNoControllerAttribute).GetTypeInfo();
|
|
var manager = GetApplicationPartManager(controllerType);
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
Assert.Empty(feature.Controllers);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetFeature_OnlyRunsOnParts_ThatImplementIApplicationPartTypeProvider()
|
|
{
|
|
// Arrange
|
|
var otherPart = new Mock<ApplicationPart>();
|
|
otherPart
|
|
.As<IApplicationPartTypeProvider>()
|
|
.Setup(t => t.Types)
|
|
.Returns(new[] { typeof(PocoController).GetTypeInfo() });
|
|
|
|
var parts = new[] {
|
|
Mock.Of<ApplicationPart>(),
|
|
new TestApplicationPart(typeof(NoSuffix).GetTypeInfo()),
|
|
otherPart.Object
|
|
};
|
|
|
|
var feature = new ControllerFeature();
|
|
|
|
var expected = new List<TypeInfo>
|
|
{
|
|
typeof(NoSuffix).GetTypeInfo(),
|
|
typeof(PocoController).GetTypeInfo()
|
|
};
|
|
|
|
var provider = new ControllerFeatureProvider();
|
|
|
|
// Act
|
|
provider.PopulateFeature(parts, feature);
|
|
|
|
// Assert
|
|
Assert.Equal(expected, feature.Controllers.ToList());
|
|
}
|
|
|
|
[Fact]
|
|
public void GetFeature_DoesNotAddDuplicates_ToTheListOfControllers()
|
|
{
|
|
// Arrange
|
|
var otherPart = new Mock<ApplicationPart>();
|
|
otherPart
|
|
.As<IApplicationPartTypeProvider>()
|
|
.Setup(t => t.Types)
|
|
.Returns(new[] { typeof(PocoController).GetTypeInfo() });
|
|
|
|
var parts = new[] {
|
|
Mock.Of<ApplicationPart>(),
|
|
new TestApplicationPart(typeof(NoSuffix)),
|
|
otherPart.Object
|
|
};
|
|
|
|
var feature = new ControllerFeature();
|
|
|
|
var expected = new List<TypeInfo>
|
|
{
|
|
typeof(NoSuffix).GetTypeInfo(),
|
|
typeof(PocoController).GetTypeInfo()
|
|
};
|
|
|
|
var provider = new ControllerFeatureProvider();
|
|
|
|
provider.PopulateFeature(parts, feature);
|
|
|
|
// Act
|
|
provider.PopulateFeature(parts, feature);
|
|
|
|
// Assert
|
|
Assert.Equal(expected, feature.Controllers.ToList());
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(typeof(BaseNonControllerController))]
|
|
[InlineData(typeof(BaseNonControllerControllerChild))]
|
|
[InlineData(typeof(BasePocoNonControllerController))]
|
|
[InlineData(typeof(BasePocoNonControllerControllerChild))]
|
|
[InlineData(typeof(NonController))]
|
|
[InlineData(typeof(NonControllerChild))]
|
|
[InlineData(typeof(BaseNonControllerAttributeChildControllerControllerAttributeController))]
|
|
[InlineData(typeof(PersonModel))] // Verifies that POCO type hierarchies that don't derive from controller return false.
|
|
public void IsController_ReturnsFalse_IfTypeOrAncestorHasNonControllerAttribute(Type type)
|
|
{
|
|
// Arrange
|
|
var manager = GetApplicationPartManager(type.GetTypeInfo());
|
|
var feature = new ControllerFeature();
|
|
|
|
// Act
|
|
manager.PopulateFeature(feature);
|
|
|
|
// Assert
|
|
Assert.Empty(feature.Controllers);
|
|
}
|
|
|
|
private static ApplicationPartManager GetApplicationPartManager(params TypeInfo[] types)
|
|
{
|
|
var manager = new ApplicationPartManager();
|
|
manager.ApplicationParts.Add(new TestApplicationPart(types));
|
|
manager.FeatureProviders.Add(new ControllerFeatureProvider());
|
|
|
|
return manager;
|
|
}
|
|
}
|
|
}
|
|
|
|
// These controllers are used to test the ControllerFeatureProvider implementation
|
|
// which REQUIRES that they be public top-level classes. To avoid having to stub out the
|
|
// implementation of this class to test it, they are just top level classes. Don't reuse
|
|
// these outside this test - find a better way or use nested classes to keep the tests
|
|
// independent.
|
|
namespace Microsoft.AspNetCore.Mvc.ControllerFeatureProviderControllers
|
|
{
|
|
public abstract class AbstractController : Controller
|
|
{
|
|
}
|
|
|
|
public class DerivedAbstractController : AbstractController
|
|
{
|
|
}
|
|
|
|
public class StoreController : Controller
|
|
{
|
|
}
|
|
|
|
public class ProductsController : ControllerBase
|
|
{
|
|
}
|
|
|
|
public class Products : ControllerBase
|
|
{
|
|
}
|
|
|
|
[Controller]
|
|
public abstract class Controller
|
|
{
|
|
}
|
|
|
|
public abstract class NoControllerAttributeBaseController
|
|
{
|
|
}
|
|
|
|
public class NoSuffixNoControllerAttribute : NoControllerAttributeBaseController
|
|
{
|
|
}
|
|
|
|
public class OpenGenericController<T> : Controller
|
|
{
|
|
}
|
|
|
|
public class DerivedGenericController : OpenGenericController<string>
|
|
{
|
|
}
|
|
|
|
public interface ITestController
|
|
{
|
|
}
|
|
|
|
public class NoSuffix : Controller
|
|
{
|
|
}
|
|
|
|
public class NoSuffixPoco
|
|
{
|
|
|
|
}
|
|
|
|
public class PocoController
|
|
{
|
|
}
|
|
|
|
[Controller]
|
|
public class CustomBase
|
|
{
|
|
|
|
}
|
|
|
|
[Controller]
|
|
public abstract class CustomAbstractBaseController
|
|
{
|
|
|
|
}
|
|
|
|
public class DescendantLevel1 : CustomBase
|
|
{
|
|
|
|
}
|
|
|
|
public class DescendantLevel2 : DescendantLevel1
|
|
{
|
|
|
|
}
|
|
|
|
public class AbstractChildWithoutSuffix : CustomAbstractBaseController
|
|
{
|
|
|
|
}
|
|
|
|
[NonController]
|
|
public class BasePocoNonControllerController
|
|
{
|
|
|
|
}
|
|
|
|
[Controller]
|
|
public class BaseNonControllerAttributeChildControllerControllerAttributeController : BaseNonControllerController
|
|
{
|
|
|
|
}
|
|
|
|
public class BasePocoNonControllerControllerChild : BasePocoNonControllerController
|
|
{
|
|
|
|
}
|
|
|
|
[NonController]
|
|
public class BaseNonControllerController : Controller
|
|
{
|
|
|
|
}
|
|
|
|
public class BaseNonControllerControllerChild : BaseNonControllerController
|
|
{
|
|
|
|
}
|
|
|
|
[NonController]
|
|
public class NonControllerChild : Controller
|
|
{
|
|
|
|
}
|
|
|
|
[NonController]
|
|
public class NonController : Controller
|
|
{
|
|
|
|
}
|
|
|
|
public class DataModelBase
|
|
{
|
|
|
|
}
|
|
|
|
public class EntityDataModel : DataModelBase
|
|
{
|
|
|
|
}
|
|
|
|
public class PersonModel : EntityDataModel
|
|
{
|
|
|
|
}
|
|
} |