using System; using System.Utility; using Chernobyl.Event; using NUnit.Framework; namespace Chernobyl.Values { /// /// Tests for types that implement /// public abstract class ValueTests where TValue : IValue { //---------------------------------------------------------------------- // Ready Tests //---------------------------------------------------------------------- [Test, Description("Ensures IValue.Provide is raised when the " + "IValue{T} is made ready.")] public virtual void ProvideRaisedWhenMadeReady() { Wrapper tested = CreateValue(); InvokeTester tester = new InvokeTester("IReadyable.BecameReady " + "should not have been invoked."); tested.TestInstance.Provide += tester.EventHandler; tester.Pass = true; tested.MakeReady(); Assert.Fail("IReadyable.BecameReady was not invoked when intended."); } [Test, Description("Ensures that event handlers that are added to " + "IValue.Provide are invoked when added to a ready" + "IValue.")] public virtual void EventHandlersAddedToReadyValueAreInvokedWhenAdded() { Wrapper tested = CreateValue(); InvokeTester tester = new InvokeTester(true, "IReadyable.BecameReady " + "should not have been invoked."); tested.MakeReady(); tested.TestInstance.Provide += tester.EventHandler; Assert.Fail("IReadyable.BecameReady was not invoked when intended."); } //---------------------------------------------------------------------- // Change Tests //---------------------------------------------------------------------- [Test, Description("A test to ensure that changing the internal value of " + "IValue to another value raises the IValue.Provide event.")] public virtual void ProvideRaisedWhenValueChanged() { Wrapper wrapper = CreateValue(); wrapper.MakeReady(); TValue value = wrapper.TestInstance; // Provide will invoke the first time it is added so we make sure // the first run is a no-op. EventHandler> invoke = (sender, e) => { /*no-op*/ }; value.Provide += (sender, e) => invoke(sender, e); // Now we can provide the method we actually want to run. invoke += (sender, e) => { e.OldValue.IsEqualTo(wrapper.ReadyValue, "ValueChangedEventArgs.OldValue"); e.NewValue.IsEqualTo(wrapper.FinalValue, "ValueChangedEventArgs.NewValue"); Assert.Pass(); }; wrapper.ChangeValue(); Assert.Fail("IValue.Provide was not raised when it should have been."); } [Test, Description("A test to ensure that setting the internal value of " + "IValue to the value it is already set at does not raise the " + "IValue.Provide event. Override this test if it is not applicable.")] public virtual void ProvideNotRaisedWhenValueIsNotChanged() { Wrapper wrapper = CreateValue(); wrapper.MakeReady(); TValue value = wrapper.TestInstance; // Provide will invoke the first time it is added so we make sure // the first run is a no-op. EventHandler> invoke = (sender, e) => { /*no-op*/ }; value.Provide += (sender, e) => invoke(sender, e); // Now we can provide the method we actually want to run. invoke += (sender, e) => Assert.Fail("IValue.Provide was raised when it should not have been."); wrapper.FakeChangeValue(); Assert.Pass(); } [Test, Description("A test to ensure that setting the internal value of " + "IValue to the value it is already set at raises the " + "IValue.Provide event if the IValue is not ready. " + "Override this test if it is not applicable.")] public virtual void ProvideRaisedWhenValueIsNotChangedButIsMadeReady() { Wrapper wrapper = CreateValue(); TValue value = wrapper.TestInstance; // Provide will invoke the first time it is added so we make sure // the first run is a no-op. EventHandler> invoke = (sender, e) => { /*no-op*/ }; value.Provide += (sender, e) => invoke(sender, e); // Now we can provide the method we actually want to run. invoke += (sender, e) => Assert.Pass(); wrapper.FakeChangeValue(); Assert.Fail("IValue.Provide was not raised when it should have been."); } /// /// The that is to be tested. The value contained /// by the returned instance must be equal to . /// The instance returned should never be re-used. /// /// The instance that is to be tested. protected abstract Wrapper CreateValue(); /// /// A type used to contain and operate on the instance to be tested. /// protected abstract class Wrapper { /// /// Initializes a new instance of the class. /// /// The instance that is to be tested. /// The value of the instance contained /// within the created by . /// The value of the instance contained /// within the when /// is invoked upon it. protected Wrapper(TValue testInstance, T readyValue, T finalValue) { TestInstance = testInstance; ReadyValue = readyValue; FinalValue = finalValue; } /// /// The instance that is to be tested. /// public TValue TestInstance { get; protected set; } /// /// Makes the ready. /// public abstract void MakeReady(); /// /// Modifies the internal value of the to /// be equal to . /// public abstract void ChangeValue(); /// /// Modifies the value of the to be equal /// to . In other words the value should /// not be changed but should still be acted /// upon as if it was being changed. /// public abstract void FakeChangeValue(); /// /// The value of the instance contained within the /// created by . /// public T ReadyValue { get; protected set; } /// /// The value of the instance contained within the /// when is invoked upon it. /// public T FinalValue { get; protected set; } } } }