using System; using System.Collections.Generic; using System.Reflection; using Chernobyl.Event; using NUnit.Framework; namespace Chernobyl.Creation { /// <summary> /// Tests for implementations of the <see cref="IFactory{T}"/> type where /// type parameter <typeparamref name="T"/> is the type of the instances /// generated by the <see cref="IFactory{T}"/> being tested. /// </summary> /// <typeparam name="T">The type of instances generated by the /// <see cref="IFactory{T}"/> being tested.</typeparam> public abstract class FactoryTests<T> { [Test, Description("A test that ensures the " + "IFactory<T>.Create(CreationCompletedEventHandler<T>) method " + "creates the instance properly.")] public void CreateSuccessTest() { IFactory<T> factory = CreateSuccessfulFactory(); var result = factory.Create(); Assert.True(GetComparer().Compare(GetProperlyCreatedItem(), result) == 0, "The Factory<T> did not create the item that was expected."); } [Test, Description("A test that ensures the " + "IFactory<T>.Create(CreationCompletedEventHandler<T>) method sets " + "the CreationEventArgs<T>.Error properly and throws a " + "TargetInvocationException when it has failed to create the instance.")] public void CreateExceptionTest() { IFactory<T> factory = CreateFailureFactory(); if (factory == null) Assert.Ignore("This test cannot be run because the IFactory<T> " + "being tested cannot fail."); else { Assert.Throws<Exception>(() => factory.Create()); } } [Test, Description("A test to ensure the " + "IFactory<T>.Created event is raised and it's " + "CreationEventArgs<T>.Error is correct when the " + "IFactory<T>.Create(CreationCompletedEventHandler<T>) method " + "is invoked.")] public void CreatedEventFailureTest() { IFactory<T> factory = CreateFailureFactory(); if (factory == null) Assert.Ignore("This test cannot be run because the IFactory<T> " + "being tested cannot fail."); else { factory.Created += (sender, e) => { Assert.AreNotEqual(null, e.Error, "The CreationEventArgs<T>.Error " + "was not equal to the value expected."); Assert.Throws<TargetInvocationException>( () => Console.WriteLine("EventFactoryTests.CreatedEventFailureTest: " + e.CreatedInstance)); Assert.Pass("EventFactory<T>.Created event was raised."); }; factory.Create(); // We should not get to this point. Assert.Fail("EventFactory<T>.Created event was not raised."); } } /// <summary> /// Generates an <see cref="IFactory{T}"/> instance that can successfully /// generate instances of type <typeparamref name="T"/>. /// </summary> /// <returns>The <see cref="IFactory{T}"/> type to test.</returns> protected abstract IFactory<T> CreateSuccessfulFactory(); /// <summary> /// Generates an <see cref="IFactory{T}"/> instance that fails to /// generate instances of type <typeparamref name="T"/> or returns null /// if the <see cref="IFactory{T}"/> does not fail to create instances. /// </summary> /// <returns>The <see cref="IFactory{T}"/> type to test or null if /// <see cref="IFactory{T}"/> that can fail cannot be generated.</returns> protected abstract IFactory<T> CreateFailureFactory(); /// <summary> /// Returns an instance of type <typeparamref name="T"/> that is /// "properly created" for the <see cref="IFactory{T}"/> being tested. /// This instance will be compared against for some of the tests. /// </summary> /// <returns>The instance to compare the creation results of the /// <see cref="IFactory{T}"/> against.</returns> protected abstract T GetProperlyCreatedItem(); /// <summary> /// The <see cref="IComparer{T}"/> used to compare two /// <typeparamref name="T"/> types. By default, /// <see cref="Comparer{T}.Default"/> is returned. /// </summary> /// <returns>The <see cref="IComparer{T}"/> to use when making /// comparisons.</returns> protected virtual IComparer<T> GetComparer() { return Comparer<T>.Default; } } }