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; }
}
}
}