I'm trying to practice unit testing in the TDD way so I created a set of interfaces that I thought could be tested somewhat independently. I'm not sure I succeeded but I'm now at the point where I'm pretty sure it's time for a mocking framework. I learn best from example and I figure someone who's very proficient will probably be able to translate this into one of them quickly (Moq or Rhino Mocks maybe? those are the ones I've found).
Unit Test:
[TestMethod]
public void RendererRendersEachWidgetByCallingBeginRenderThenEndRender()
{
// Mocks/Stubs
ISpace space = new MockSpace();
IWorld world = new MockWorld();
IWidget widget1 = new MockWidget("widget1");
IWidget widget2 = new MockWidget("widget2");
world.Add(widget1);
world.Add(widget2);
// Object under test
IRenderer target = new Renderer(world, space);
target.Render();
// verify BeginRender is called
Assert.IsTrue((space as MockSpace).results.Contains("Begin Render " + widget1.Id));
Assert.IsTrue((space as MockSpace).results.Contains("Begin Render " + widget2.Id));
// verify EndRender is called
Assert.IsTrue((space as MockSpace).results.Contains("End Render " + widget1.Id));
Assert.IsTrue((space as MockSpace).results.Contains("End Render " + widget2.Id));
// verify BeginRender is called before EndRender
var orderedResults = (space as MockSpace).results.Select((s, i) => Tuple.Create(i, s));
Assert.IsTrue(
(orderedResults.Single(x => x.Item2 == "Begin Render " + widget1.Id).Item1) <
(orderedResults.Single(x => x.Item2 == "End Render " + widget1.Id).Item1));
Assert.IsTrue(
(orderedResults.Single(x => x.Item2 == "Begin Render " + widget2.Id).Item1) <
(orderedResults.Single(x => x.Item2 == "End Render " + widget2.Id).Item1));
}
Here is a Rhino.Mocks version. I've taken liberties where the internals of the Renderer
were unknown.
As you can see, there is a fair amount of setup involved, but in this case you won't have had to create all those mock object types manually.
[TestMethod]
public void RendererRendersEachWidgetByCallingBeginRenderThenEndRender()
{
// Mocks/Stubs
var orderedResultList = new List<string>();
var space = MockRepository.GenerateStub<ISpace>();
space.Stub(s => s.BeginRender(Arg<IWidget>.Is.Anything))
.WhenCalled(x => orderedResultList.Add("Begin Render " + ((IWidget)x.Arguments[0]).Id));
space.Stub(s => s.EndRender(Arg<IWidget>.Is.Anything))
.WhenCalled(x => orderedResultList.Add("End Render " + ((IWidget)x.Arguments[0]).Id));
var world = MockRepository.GenerateStub<IWorld>();
var widget1 = MockRepository.GenerateStub<IWidget>();
widget1.Stub(w => w.Id).Return("widget1"); // assuming no public setter for this property
var widget2 = MockRepository.GenerateStub<IWidget>();
widget2.Stub(w => w.Id).Return("widget2"); // assuming no public setter for this property
var widgetList = new List<IWidget>{ widget1, widget2 };
world.Stub(w => w.Widgets).Return(widgetList);
// Object under test
IRenderer target = new Renderer(world, space);
target.Render();
// verify BeginRender is called
space.AssertWasCalled(s => s.BeginRender(Arg<IWidget>.Is.Same(widget1)));
space.AssertWasCalled(s => s.BeginRender(Arg<IWidget>.Is.Same(widget2)));
// verify EndRender is called
space.AssertWasCalled(s => s.EndRender(Arg<IWidget>.Is.Same(widget1)));
space.AssertWasCalled(s => s.EndRender(Arg<IWidget>.Is.Same(widget2)));
// verify BeginRender is called before EndRender
var orderedResults = orderedResultList.Select((s, i) => Tuple.Create(i, s));
Assert.IsTrue(
(orderedResults.Single(x => x.Item2 == "Begin Render " + widget1.Id).Item1) <
(orderedResults.Single(x => x.Item2 == "End Render " + widget1.Id).Item1));
Assert.IsTrue(
(orderedResults.Single(x => x.Item2 == "Begin Render " + widget2.Id).Item1) <
(orderedResults.Single(x => x.Item2 == "End Render " + widget2.Id).Item1));
}