Thursday, February 15, 2007

base test class

one thing that can make your tests real messy, real fast is duplicated code. however, with mocks, its really hard to get rid of duplication and keep your code readable.

a simple first step to uniform tests is a base test class that you inherit from in all your classes. use this class to setup your mock repository, replay, verify, tear down and do any custom setup your application needs for all your tests.



[TestFixture]
public void BaseTest
{
protected MockRepository _mocks;


[SetUp]
public virtual void Setup()
{
_mocks = new MockRepository();
}

[TearDown]
public virtual void TearDown()
{
}

protected virtual void FinalizeAll()
{
_mocks.ReplayAll();
}

protected void CreateMock<T>()
{
return _mocks.CreateMock<T>();
}

protected T XamlSerializeAndDeserialize<T>(T original)
{
using (MemoryStream stream = new MemoryStream())
{
XamlWriter.Save(original, stream);
stream.Position = 0;
return (T)XamlReader.Load(stream);
}
}
}


We keep the MockRepository protected because there are so many methods on it that inheritors may want to use, but use the base tests methods usages of _mocks when they exist. Also, we call the method that ReplaysAll "FinalizeAll" because methods that override often do more than just replay the mocks, they finalize the state of the other objects in the test. However, this may not be the best name, considering what "finalize" means in the c# world...

If you use an object management framework, logging or other common mocks, the base class can take the responsibility of setting those up.

As you can see, we added a method, "XamlSerializeAndDeserialize," since we test this in many of our classes, you could put this in a separate Assert class too, but it really depends on how often its used and what your team likes.

As your tests evolve, factories to create common mock objects and classes to do custom Asserts are also really helpful. One test class we've found really helpful is a PropertyChangedEventTester that will hook into any class that implements INotifyPropertyChanged and keep track of events.

No comments: