216 lines
8.0 KiB
C#
216 lines
8.0 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 Microsoft.AspNet.Mvc.ActionConstraints;
|
|
using Microsoft.AspNet.Mvc.ApplicationModels;
|
|
using Microsoft.AspNet.Mvc.Core;
|
|
using Microsoft.AspNet.Mvc.Filters;
|
|
using Microsoft.Framework.DependencyInjection;
|
|
using Microsoft.Framework.OptionsModel;
|
|
using Moq;
|
|
using Xunit;
|
|
|
|
namespace Microsoft.AspNet.Mvc
|
|
{
|
|
public class MvcCoreServiceCollectionExtensionsTest
|
|
{
|
|
// Some MVC services can be registered multiple times, for example, 'IConfigureOptions<MvcOptions>' can
|
|
// be registered by calling 'ConfigureMvc(...)' before the call to 'AddMvc()' in which case the options
|
|
// configuration is run in the order they were registered.
|
|
//
|
|
// For these kind of multi registration service types, we want to make sure that MVC will still add its
|
|
// services if the implementation type is different.
|
|
[Fact]
|
|
public void MultiRegistrationServiceTypes_AreRegistered_MultipleTimes()
|
|
{
|
|
// Arrange
|
|
var services = new ServiceCollection();
|
|
|
|
// Register a mock implementation of each service, AddMvcServices should add another implemenetation.
|
|
foreach (var serviceType in MutliRegistrationServiceTypes)
|
|
{
|
|
var mockType = typeof(Mock<>).MakeGenericType(serviceType.Key);
|
|
services.Add(ServiceDescriptor.Transient(serviceType.Key, mockType));
|
|
}
|
|
|
|
// Act
|
|
MvcCoreServiceCollectionExtensions.AddMvcCoreServices(services);
|
|
|
|
// Assert
|
|
foreach (var serviceType in MutliRegistrationServiceTypes)
|
|
{
|
|
AssertServiceCountEquals(services, serviceType.Key, serviceType.Value.Length + 1);
|
|
|
|
foreach (var implementationType in serviceType.Value)
|
|
{
|
|
AssertContainsSingle(services, serviceType.Key, implementationType);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void SingleRegistrationServiceTypes_AreNotRegistered_MultipleTimes()
|
|
{
|
|
// Arrange
|
|
var services = new ServiceCollection();
|
|
|
|
// Register a mock implementation of each service, AddMvcServices should not replace it.
|
|
foreach (var serviceType in SingleRegistrationServiceTypes)
|
|
{
|
|
var mockType = typeof(Mock<>).MakeGenericType(serviceType);
|
|
services.Add(ServiceDescriptor.Transient(serviceType, mockType));
|
|
}
|
|
|
|
// Act
|
|
MvcCoreServiceCollectionExtensions.AddMvcCoreServices(services);
|
|
|
|
// Assert
|
|
foreach (var singleRegistrationType in SingleRegistrationServiceTypes)
|
|
{
|
|
AssertServiceCountEquals(services, singleRegistrationType, 1);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void AddMvcServicesTwice_DoesNotAddDuplicates()
|
|
{
|
|
// Arrange
|
|
var services = new ServiceCollection();
|
|
|
|
// Act
|
|
MvcCoreServiceCollectionExtensions.AddMvcCoreServices(services);
|
|
MvcCoreServiceCollectionExtensions.AddMvcCoreServices(services);
|
|
|
|
// Assert
|
|
var singleRegistrationServiceTypes = SingleRegistrationServiceTypes;
|
|
foreach (var service in services)
|
|
{
|
|
if (singleRegistrationServiceTypes.Contains(service.ServiceType))
|
|
{
|
|
// 'single-registration' services should only have one implementation registered.
|
|
AssertServiceCountEquals(services, service.ServiceType, 1);
|
|
}
|
|
else
|
|
{
|
|
// 'multi-registration' services should only have one *instance* of each implementation registered.
|
|
AssertContainsSingle(services, service.ServiceType, service.ImplementationType);
|
|
}
|
|
}
|
|
}
|
|
|
|
private IEnumerable<Type> SingleRegistrationServiceTypes
|
|
{
|
|
get
|
|
{
|
|
var services = new ServiceCollection();
|
|
MvcCoreServiceCollectionExtensions.AddMvcCoreServices(services);
|
|
|
|
var multiRegistrationServiceTypes = MutliRegistrationServiceTypes;
|
|
return services
|
|
.Where(sd => !multiRegistrationServiceTypes.Keys.Contains(sd.ServiceType))
|
|
.Select(sd => sd.ServiceType);
|
|
}
|
|
}
|
|
|
|
private Dictionary<Type, Type[]> MutliRegistrationServiceTypes
|
|
{
|
|
get
|
|
{
|
|
return new Dictionary<Type, Type[]>()
|
|
{
|
|
{
|
|
typeof(IConfigureOptions<MvcOptions>),
|
|
new Type[]
|
|
{
|
|
typeof(CoreMvcOptionsSetup),
|
|
}
|
|
},
|
|
{
|
|
typeof(IActionConstraintProvider),
|
|
new Type[]
|
|
{
|
|
typeof(DefaultActionConstraintProvider),
|
|
}
|
|
},
|
|
{
|
|
typeof(IActionDescriptorProvider),
|
|
new Type[]
|
|
{
|
|
typeof(ControllerActionDescriptorProvider),
|
|
}
|
|
},
|
|
{
|
|
typeof(IActionInvokerProvider),
|
|
new Type[]
|
|
{
|
|
typeof(ControllerActionInvokerProvider),
|
|
}
|
|
},
|
|
{
|
|
typeof(IFilterProvider),
|
|
new Type[]
|
|
{
|
|
typeof(DefaultFilterProvider),
|
|
}
|
|
},
|
|
{
|
|
typeof(IControllerPropertyActivator),
|
|
new Type[]
|
|
{
|
|
typeof(DefaultControllerPropertyActivator),
|
|
}
|
|
},
|
|
{
|
|
typeof(IApplicationModelProvider),
|
|
new Type[]
|
|
{
|
|
typeof(DefaultApplicationModelProvider),
|
|
}
|
|
},
|
|
};
|
|
}
|
|
}
|
|
|
|
private void AssertServiceCountEquals(
|
|
IServiceCollection services,
|
|
Type serviceType,
|
|
int expectedServiceRegistrationCount)
|
|
{
|
|
var serviceDescriptors = services.Where(serviceDescriptor => serviceDescriptor.ServiceType == serviceType);
|
|
var actual = serviceDescriptors.Count();
|
|
|
|
Assert.True(
|
|
(expectedServiceRegistrationCount == actual),
|
|
$"Expected service type '{serviceType}' to be registered {expectedServiceRegistrationCount}" +
|
|
$" time(s) but was actually registered {actual} time(s).");
|
|
}
|
|
|
|
private void AssertContainsSingle(
|
|
IServiceCollection services,
|
|
Type serviceType,
|
|
Type implementationType)
|
|
{
|
|
var matches = services
|
|
.Where(sd =>
|
|
sd.ServiceType == serviceType &&
|
|
sd.ImplementationType == implementationType)
|
|
.ToArray();
|
|
|
|
if (matches.Length == 0)
|
|
{
|
|
Assert.True(
|
|
false,
|
|
$"Could not find an instance of {implementationType} registered as {serviceType}");
|
|
}
|
|
else if (matches.Length > 1)
|
|
{
|
|
Assert.True(
|
|
false,
|
|
$"Found multiple instances of {implementationType} registered as {serviceType}");
|
|
}
|
|
}
|
|
}
|
|
} |