Sunday, April 04, 2010

Very Simple Sequencer for Moq...

Following is a very simple tool for testing Moq...


public class MoqSequence
{
  private int expectedSteps;
  private int actualSteps;

  private MoqSequence() { }

  internal static MoqSequence GetInstance()
  {
    return new MoqSequence();
  }

  private class SequenceException : Exception
  {
    private SequenceException(string message)
      : base(message)
    {
    }

    internal static SequenceException GetInstance(
      int expectedStep, int actualStep)
    {
      return GetInstance(
        "Step " + expectedStep + " executed when step "
        + actualStep + " should have been.");
    }

    internal static SequenceException GetInstance(
      string message)
    {
      return new SequenceException(message);
    }
  }

  public void InSequence<T>(ISetup<T> iSetup)
    where T : class
  {
    var expectedStep = expectedSteps++;

    iSetup.Callback(
      () =>
      {
        if (actualSteps != expectedStep)
        {
          throw SequenceException.GetInstance(
            expectedStep, actualSteps);
        }

        actualSteps++;
      });
  }

  public void Verify()
  {
    if (expectedSteps != actualSteps)
    {
      throw SequenceException.GetInstance(
        "Expected " + expectedSteps + 
        " steps but only got " + actualSteps +
        " steps");
    }
  }
}
Here is an example of how to use it:



[Test]
public void ExecutesStepsInCorrectOrder()
{
  var sequence = MoqSequence.GetInstance();

  sequence.InSequence(transactionMock.Setup(
    t => t.Lock()));
  sequence.InSequence(transactionMock.Setup(
    t => t.TransferAssetsIntoEscrow(escrowMock.Object)));
  sequence.InSequence(transactionMock.Setup(
    t => t.SchedulePayouts(escrowMock.Object)));
  sequence.InSequence(escrowMock.Setup(
    e => e.ReconcilePayoutsWithHoldings()));
  sequence.InSequence(escrowMock.Setup(
    e => e.ExecutePayouts()));
  sequence.InSequence(transactionMock.Setup(
    t => t.Complete()));

  transactionCoordinator
    .RunTransaction(transactionMock.Object);

  sequence.Verify();
}