The latest edition of Testing on the Toilet linked above gave me an idea on how to streamline the tests we’ve been writing. In our presenter and model tests, we have a ton of mocking noise and boilerplate code that has to be written on every test class. Here’s an example:
[TestClass] public class CDCSurveyPresenterTest { [TestInitialize] public void Initialize() { this.mocks = new MockRepository(); this.model = this.mocks.DynamicMock(); this.view = this.mocks.DynamicMock (); this.navigationContext = this.mocks.DynamicMock (); Expect.Call(this.navigationContext.Get ()) .Return(this.model).Repeat.Any(); Expect.Call(this.navigationContext.Get ()) .Return(this.view).Repeat.Any(); } [TestCleanup] public void Cleanup() { this.mocks.VerifyAll(); } // TESTS GO HERE }
In every test class, we create MockRepository, create the necessary dynamic mocks and set up the exact same expectations on the navigation context class. It gets pretty painful after time and adds quite a bit of unnecessary code to all the test classes. So, it seems like a perfectly ripe situation for moving all that to a base class that every test class can inherit from.
Here’s the base class:
[TestClass] public abstract class RFPresenterTestClasswhere M : class where V : class { protected V View { get { return this.view; } } protected M Model { get { return this.model; } } protected MockRepository Mocks { get { return this.mocks; } } protected INavigationContext NavigationContext { get { return this.context; } } [TestInitialize] public virtual void Initialize() { this.mocks = new MockRepository(); this.view = this.mocks.DynamicMock (); this.model = this.mocks.DynamicMock (); this.context = this.mocks.DynamicMock (); Expect.Call(this.context.Get ()).Return(this.view).Repeat.Any(); Expect.Call(this.context.Get ()).Return(this.model).Repeat.Any(); } [TestCleanup] public void Cleanup() { this.mocks.VerifyAll(); } private MockRepository mocks = null; private V view = null; private M model = null; private INavigationContext context = null; }
All the mocking code and setup is moved into an abstract class using generics to greatly simplify the creation of objects. Once that’s done, we only have to extend this original test class like so:
[TestClass] public class CDCSurveyPresenterTest : RFPresenterTestClass{ // Test Classes go here, set up and teardown has been moved to the base class }
All the setup and teardown is moved to the base class making our test classes just about the tests without all the mocking noise. This makes the test code base much more stable and readable over time as well as making test writing a lot easier because all the boilerplate code is gone.