Simplify Your Unit Tests With Automocking: Part 2 – Establishing Context


Following my helper methods in the base context specification class that we use, I decided to simplify the entire process of setting the context in which the tests are running. Specifically, I wanted to get rid of the constant declaration and instantiation of the System Under Test (SUT) field – the class that is having it’s method called to ensure it behaves correctly.

 

A Base Context With SUT Setup

Instead of having to manually call out to the MockingKernel directly, to retrieve the system under test (SUT), like this:</p>

   1: public class when_doing_something_with_that_thing : ContextSpecification

   2: {

   3:     protected MyPresenter SUT;

   4:     

   5:     protected override void EstablishContext()

   6:     {

   7:         SUT = Get<MyPresenter>();

   8:     }

   9:     

  10:     protected override void When()

  11:     {

  12:         SUT.DoSomething();

  13:     }

  14:     

  15:     [Test]

  16:     public void it_should_do_that_thing()

  17:     {

  18:         AssertWasCalled<IMyView>(v => v.ThatThing());

  19:     }

  20: }

</div> </div>

I added a generics version of the ContextSpecification class to our set of spec helpers. I took the EstablishContext method out of the above code and dropped it into a ContextSpecification: </p>

   1: public class ContextSpecification<T>: ContextSpecification

   2: {

   3:     protected T SUT;

   4:     

   5:     override void EstablishContext()

   6:     {

   7:         SUT = MicroKernel.Get<T>();

   8:     }

   9: }

</div> </div>

Now I can declare a spec without having to setup an EstablishContext method, if I don’t need one, and I don’t need to declare a protected SUT field:

</p>
   1: public class when_doing_something_with_that_thing : ContextSpecification<MyPresenter>

   2: {

   3:     protected override void When()

   4:     {

   5:         SUT.DoSomething();

   6:     }

   7:     

   8:     [Test]

   9:     public void it_should_do_that_thing()

  10:     {

  11:         AssertWasCalled<IMyView>(v => v.ThatThing());

  12:     }

  13: }

</div> </div>

If I do need to set up additional code – stub methods, for example, I can still override the EstablishContext method. I just need to make sure I call to the base.EstablishContext so that I still get my SUT setup.

   1: protected override EstablishContext()

   2: {

   3:     base.EstablishContext();

   4:     Get<ISomeService>().Stub(v => v.ThisThingIsCalled()).Return("some value);

   5: }

</div> </div>

 

A Complete Example

The complete example that yesterday’s post ended with is even easier to read, now. I’ve eliminated another chunk of code and the test gets straight to the heart of what is happening – the behavior of the system.

   1: public class when_doing_something_with_that_thing : ContextSpecification<MyPresenter>

   2: {

   3:     protected override void When()

   4:     {

   5:         SUT.DoSomething();

   6:     }

   7:     

   8:     [Test]

   9:     public void it_should_do_that_thing()

  10:     {

  11:         AssertWasCalled<IMyView>(v => v.ThatThing());

  12:     }

  13:  

  14:     [Test]

  15:     public void it_should_do_the_other_thing_twice()

  16:     {

  17:         AssertWasCalled<IMyView>(v => v.TheOtherThing(), mo => mo.Repeat.Twice());

  18:     }

  19: }

</div> </div>

 

Other Considerations

I’m obviously very happy with what I’ve been able to do with the Ninject.RhinoMocks automocking container. However, there is a potential danger in using an auto mocking container. Stay tuned for tomorrow’s post to find out more about that danger and how you can help your team avoid it.

Simplify Your Unit Tests With Auto Mocking: Part 1 – Helper Methods