Search code examples
c#mockingtddmoqrhino-mocks

How would this unit test translate to leveraging a mocking framework?


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));
    }

Solution

  • 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));
    }