Samples

Scenario

For most samples here the following scenario is used:

Class under test:

public class Testee
{
    private IMyCollection myCollection;

    public Testee(IMyCollection myCollection)
    {
        this.myCollection = myCollection;
    }

    public void CallDescribeTo(TextWriter writer)
    {
        myCollection.DescribeTo(writer);
    }
    
    public void AddRange(IEnumerable collection)
    {
        myCollection.AddRange(collection);
    }
}
            

The interface the testee is dependent on

public interface IMyCollection
{
    string Name { get; set; }

    object this[int index] { get; set; }

    event EventHandler ElementAdded;

    void DescribeTo(TextWriter writer);
    
    void GetStatistics(out int currentNumberOfElements, out int maximalNumberOfElements);

    T GetElement(int index);

    void AddRange(IEnumerable collection);
}
            

TestFixture

I'll use this TestFixture for all tests. Note that the unit tests are still missing they are explained per sample.

[TestFixture]
public class Documentation
{
    private Testee testee;
    private Mockery mockery;

    public void SetUp()
    {
        mockery = new Mockery();

        IMyCollection myCollection = mockery.NewMock<IMyCollection>();
        
        testee = new Testee(myCollection);
    }

    // see samples below for individual tests    
}            
            

Expect a method call

The following unit test verifies that when CallDesribeTo is called on the testee the method DescribeTo is called on the mock with the writer we passed to the method.

[Test]
public void ExpectMethodCall()
{
    TextWriter writer = new StringWriter();
    Expect.Once.On(testee).Method("DescribeTo").With(writer);

    testee.CallDescribeTo(writer);

    mockery.VerifyAllExpectationsHaveBeenMet();
}
            

If you are not interested whether the correct writer is passed you let the With away:

Expect.Once.On(testee).Method("DescribeTo");

If you want to test how your code reacts to exceptions you can change the expectation to:

Expect.Once.On(testee).Method("DescribeTo").With(writer).Will(Throw.Exception(new Exception()));

Of course it would be better to use a more specific exception for your scenario.

Match on collection elements

This sample shows you how you can implement your own Matcher that checks whether the collection passed to a method has the elements you expect:

[Test]
public void ExpectationThatVerifiesCollectionElements()
{
    List aList = new List();
    aList.Add(1);
    aList.Add(2);
    aList.Add(3);

    Expect.Once.On(myCollection).Method("AddRange").With(new MyCollectionMatcher(aList));
    
    testee.AddRange(aList);

    mockery.VerifyAllExpectationsHaveBeenMet();
}

[Test]
public void ExpectationThatVerifiesCollectionElementsFailing()
{
    List aList = new List();
    aList.Add(1);
    aList.Add(2);
    aList.Add(3);

    Expect.Once.On(myCollection).Method("AddRange").With(new MyCollectionMatcher(aList));

    aList.Insert(1, 9);
    testee.AddRange(aList);

    mockery.VerifyAllExpectationsHaveBeenMet();
}

public class MyCollectionMatcher : Matcher
{
    private readonly List collection;

    public MyCollectionMatcher(IEnumerable expected)
    {
        collection = new List();
        foreach (object element in expected)
        {
            collection.Add(element);
        }
    }

    public override bool Matches(object o)
    {
        if (o is IEnumerable)
        {
            return CheckElements((IEnumerable)o);    
        }
        else
        {
            return false;
        }
    }

    public override void DescribeTo(TextWriter writer)
    {
        writer.Write("collection containing elements ");
        foreach (object o in collection)
        {
            writer.Write(" ");
            writer.Write(o);
        }
    }

    private bool CheckElements(IEnumerable collectionToCheck)
    {
        IEnumerator expected = collection.GetEnumerator();
        IEnumerator actual = collectionToCheck.GetEnumerator();

        while (expected.MoveNext())
        {
            if (actual.MoveNext())
            {
                if (!expected.Current.Equals(actual.Current))
                {
                    return false;
                }
            }
            else
            {
                return false; // not the same number of elements
            }
        }

        return true;
    }
}
            
        
            

To be continued. For more samples please have a look at the acceptance tests in the source code of NMock2.