using System.Collections.Generic;
using NUnit.Framework;
namespace System.ComponentModel.Design
{
///
/// A set of reusable tests for testing types that implement
/// .
///
public abstract class ServiceContainerTests : ServiceProviderTests
{
[Test, Description("A test that ensures the " +
"IServiceContainer.AddService(Type, Object) method sets the service " +
"properly.")]
public void AddServiceTypeObjectTest()
{
IServiceContainer serviceContainer = CreateServiceContainer();
ICollection collection = new List();
Type collectionType = typeof(ICollection);
serviceContainer.AddService(collectionType, collection);
object collectionService = serviceContainer.GetService(collectionType);
Assert.AreEqual(collection, collectionService, "Unexpected service " +
"was retrieved.");
}
[Test, Description("A test that ensures the " +
"IServiceContainer.AddService(Type, Object, Boolean) method sets " +
"the service properly and does so on the parents if told to do so.")]
public void AddServiceTypeObjectBoolTest()
{
ICollection service = new List();
Type serviceType = typeof(ICollection);
// Check the promotion of a service
{
IServiceContainer serviceContainer = CreateServiceContainer();
serviceContainer.AddService(serviceType, service, true);
CheckServicesInHierarchy(serviceContainer, serviceType, service);
}
// Check the lack of promotion of a service
{
IServiceContainer serviceContainer = CreateServiceContainer();
serviceContainer.AddService(serviceType, service, false);
CheckServicesInHierarchy(serviceContainer, serviceType, null);
}
}
[Test, Description("A test that ensures the " +
"IServiceContainer.AddService(Type, ServiceCreatorCallback) method " +
"sets the service properly.")]
public void AddServiceTypeServiceCreatorCallbackTest()
{
IServiceContainer serviceContainer = CreateServiceContainer();
ServiceCreatorCallbackTester tester = new ServiceCreatorCallbackTester();
Type collectionType = typeof(ICollection);
serviceContainer.AddService(collectionType, tester.Callback);
Assert.AreEqual(false, tester.Invoked, "The ServiceCreatorCallback should " +
"not have been invoked.");
object collectionService = serviceContainer.GetService(collectionType);
Assert.AreEqual(true, tester.Invoked, "The ServiceCreatorCallback should " +
"have been invoked.");
Assert.AreEqual(tester.Service, collectionService, "Unexpected service " +
"was retrieved.");
}
///
/// A helper class for use in the
/// method. This
/// class stores the being injected as well as the
/// property which indicates whether the callback
/// method was invoked or not.
///
class ServiceCreatorCallbackTester
{
public ServiceCreatorCallbackTester()
{
Invoked = false;
Service = new List();
}
public object Callback(IServiceContainer servCont, Type type)
{
Invoked = true;
return Service;
}
public bool Invoked { get; private set; }
public ICollection Service { get; private set; }
}
[Test, Description("A test that ensures the " +
"IServiceContainer.AddService(Type, ServiceCreatorCallback, Boolean) " +
"method sets the service properly and does so on the parents if told " +
"to do so.")]
public void AddServiceTypeServiceCreatorCallbackBooleanTest()
{
ICollection service = new List();
Type serviceType = typeof(ICollection);
// Check the promotion of a service
{
IServiceContainer serviceContainer = CreateServiceContainer();
serviceContainer.AddService(serviceType, (servCont, type) => service, true);
CheckServicesInHierarchy(serviceContainer, serviceType, service);
}
// Check the lack of promotion of a service
{
IServiceContainer serviceContainer = CreateServiceContainer();
serviceContainer.AddService(serviceType, (servCont, type) => service, false);
CheckServicesInHierarchy(serviceContainer, serviceType, null);
}
}
[Test, Description("A test that ensures IServiceContainer.Remove(Type) " +
"properly removes a service from the IServicesContainer container.")]
public void RemoveServiceTypeTest()
{
IServiceContainer serviceContainer = CreateServiceContainer();
ICollection collection = new List();
Type serviceType = typeof(ICollection);
serviceContainer.AddService(serviceType, collection);
RemoveServiceCheck(serviceContainer, collection, serviceType, (servCont, type) => serviceContainer.RemoveService(type));
}
[Test, Description("A test that ensures " +
"IServiceContainer.Remove(Type, Boolean) properly removes a service " +
"from the IServicesContainer container and propagates the change to " +
"the parent IServiceContainer.")]
public void RemoveServiceTypeBooleanTest()
{
ICollection collection = new List();
Type serviceType = typeof(ICollection);
// Check the promotion of service removal.
{
IServiceContainer serviceContainer = CreateServiceContainer();
serviceContainer.AddService(serviceType, collection, true);
RemoveServiceCheck(serviceContainer, collection, serviceType, (servCont, type) => serviceContainer.RemoveService(type, true));
CheckServicesInHierarchy(serviceContainer, serviceType, null);
}
// Check the lack of promotion of a service removal.
{
IServiceContainer serviceContainer = CreateServiceContainer();
serviceContainer.AddService(serviceType, collection, true);
RemoveServiceCheck(serviceContainer, collection, serviceType, (servCont, type) => serviceContainer.RemoveService(type, false));
CheckServicesInHierarchy(serviceContainer, serviceType, collection);
}
}
[Test, Description("A test that ensures IServiceContainers can properly " +
"override properly added services.")]
public void OverrideServiceTest()
{
IServiceContainer serviceContainer = CreateServiceContainer();
Type serviceType = typeof (ICollection);
ICollection service1 = new List();
ICollection service2 = new List();
// Add the service and ensure we can retrieve it as expected.
{
serviceContainer.AddService(serviceType, service1);
object service = serviceContainer.GetService(serviceType);
Assert.AreEqual(service1, service);
}
// Now override the service we just added and ensure we can retrieve
// it as expected.
{
serviceContainer.AddService(serviceType, service2);
object service = serviceContainer.GetService(serviceType);
Assert.AreEqual(service2, service);
}
}
///
/// Creates the to test. This method
/// should always create a new instance. The
/// must contain a service of type that
/// is not null and equal to .
/// The must also have the number of
/// ancestors specified by .
///
/// The instance to test.
protected abstract IServiceContainer CreateServiceContainer();
///
/// Retrieves the parent of the
/// passed in.
///
/// The
/// whose parent is to be retrieved.
/// The parent of the
/// instance or null if they instance has no parent.
protected abstract IServiceContainer GetParent(IServiceContainer serviceContainer);
protected override IServiceProvider CreateServiceProvider()
{
return CreateServiceContainer();
}
///
/// The number of ancestors the returned
/// by is expected to have. The
/// value of this field is 2.
///
protected const int ExpectedServiceAncestorCount = 2;
///
/// Ensures the and its ancestors
/// can handle the promotion of services, or lack thereof.
///
/// The service container whose
/// ancestors are to be checked to see if they contain the
/// .
/// The type of the service to check for in
/// the .
/// The service that is expected in the
/// .
void CheckServicesInHierarchy(IServiceContainer serviceContainer, Type serviceType, object expectedService)
{
serviceContainer = GetParent(serviceContainer);
// Check the ancestors of the serviceContainer to see if the service
// was added to them. While we are doing that, we'll keep a count to
// ensure the IServiceContainer has the proper number of ancestors.
int serviceContainerCount = 0;
do
{
++serviceContainerCount;
object actualService = serviceContainer.GetService(serviceType);
Assert.AreEqual(expectedService, actualService, "Unexpected service " +
"was retrieved.");
serviceContainer = GetParent(serviceContainer);
} while (serviceContainer != null);
Assert.AreEqual(ExpectedServiceAncestorCount, serviceContainerCount);
}
///
/// Tests an to see if it can handle
/// the removal of a service.
///
/// The
/// to test.
/// The service that is to be removed
/// from the . Before the service is
/// removed, the is checked to see
/// if it exists.
/// The of the service to
/// remove.
/// The method to be invoked that will
/// remove the service of from the
/// specified.
static void RemoveServiceCheck(IServiceContainer serviceContainer, object serviceToBeRemoved, Type serviceType, Action removeService)
{
object collectionService = serviceContainer.GetService(serviceType);
Assert.AreEqual(serviceToBeRemoved, collectionService, "Unexpected service " +
"was retrieved.");
removeService(serviceContainer, serviceType);
collectionService = serviceContainer.GetService(serviceType);
Assert.AreEqual(null, collectionService, "Service should have been " +
"null");
}
}
}