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

After working on the Ninject.RhinoMocks automocking container, I started using it in my current project right away and it wasn’t long before I started simplifying the usage of it with helper methods in my base test class.

 

From “MockingKernel.Get<T>()” To “Get<T>()”

I got tired of calling MockingKernel.Get<MyClass>() all over the place, so I created a helper method in my base ContextSpecification class called Get<T>(). This method does nothing more than forward calls to the MockingKernel.Get method, but it could easily be enhanced to do something more – like caching the object retrieved, so that the IoC container is not always resolving (even though it resolves to a singleton).

   1: protected T Get<T>()

   2: {

   3:     return MockingKernel.Get<T>();

   4: }

This is a small change, but it makes a lot of code easier to ready. Compare this:

   1: [Test]

   2: public void it_should_do_that_thing()

   3: {

   4:     MockingKernel.Get<IMyView>().AssertWasCalled(v => v.ThatThing());

   5: }

To this:

   1: [Test]

   2: public void it_should_do_that_thing()

   3: {

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

   5: }

A small amount of code reduction and a little easier to read.

 

From “Get<IMyView>().AssertWasCalled(…)” to “AssertWasCalled<IMyView>(…)”

After adding the Get<T> code, I realized that I could simplify the assertion even further by creating a helper method that would call Get<T> for me. RhinoMocks has two methods for AssertWasCalled. The first just takes the method and sets some defaults, like only expecting 1 call. The second allows you to specify method options for more advanced needs. I created to AssertWasCalled<T> methods to mimic the RhinoMocks methods and call Get<T> for me:

   1: protected void AssertWasCalled<T>(Action<T> action)

   2: {

   3:     T mock = Get<T>();

   4:     mock.AssertWasCalled(action);

   5: }

   6:     

   7: protected void AssertWasCalled<T>(Action<T> action, Action<IMethodOptions<object>> methodOptions)

   8: {

   9:     T mock = Get<T>();

  10:     mock.AssertWasCalled(action, methodOptions);

  11: }

This allowed me to simplify my specs down even further:

   1: [Test]

   2: public void it_should_do_that_thing()

   3: {

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

   5: }

   6:  

   7: [Test]

   8: public void it_should_do_the_other_thing_twice()

   9: {

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

  11: }

This is less code to read and easier to understand.

 

A Full Spec Example

With these helper methods in place, a full specification is much easier to read, now:

   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:  

  21:     [Test]

  22:     public void it_should_do_the_other_thing_twice()

  23:     {

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

  25:     }

  26: }

 

But Wait! There’s More!

It gets even better! In tomorrow’s blog post – part 2 of simplifying unit tests with automocking – I’ll reduce the full specification code even further by eliminating the need to declare and setup the System Under Test (SUT).


Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Derick Bailey

Derick Bailey is an entrepreneur, problem solver (and creator? :P ), software developer, screecaster, writer, blogger, speaker and technology leader in central Texas (north of Austin). He runs SignalLeaf.com - the amazingly awesome podcast audio hosting service that everyone should be using, and WatchMeCode.net where he throws down the JavaScript gauntlets to get you up to speed. He has been a professional software developer since the late 90's, and has been writing code since the late 80's. Find me on twitter: @derickbailey, @mutedsolutions, @backbonejsclass Find me on the web: SignalLeaf, WatchMeCode, Kendo UI blog, MarionetteJS, My Github profile, On Google+.
This entry was posted in .NET, AutoMocking, Behavior Driven Development, C#, Ninject, Refactoring, RhinoMocks, Unit Testing. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://scottbellware.com Scott Bellware

    That “SUT” stuff trades solubility for something that is purely a programmer’s pursuit: abstraction for its own sake. Beyond mere readability, specs are supposed to be instantly knowable. That won’t happen when you generalize the subject of a specification behind a symbolic name like “SUT”.

    It’s common enough for programmer psychology to take us this far into the pursuit of abstractness, but it doesn’t serve the goal that documenting a system with context specification is meant to serve.

    As a programmer, it’s easy to fall into the programmer psychology trap. One of the principal purposes of context specification is to create a means to practice not falling into that trap.

    It’s not an exercise in programmers’ solutions to reuse and abstraction or even in strict terseness (especially because terseness doesn’t have an absolute causal relationship with solubility). The point is to have concrete, experiential examples of when programmer psychology drags us off the rails of learning how to communicate celarly and immediately with entities outside of our own skulls.

    This “SUT” stuff is one of the clearest (and one of the most common) mistakes in interpretation of context specification. It demonstrates clearly and directly, in a way that a programmer should be able to observe and learn from, that the programmer mind and the communicator mind is often at odds.

    Context specification is about serving the needs of communicator mind rather than the programmer mind. The real challenge with all this is that the programmer mind, in its near-infinite capacity to over-estimate itself, usually fails to see that it is failing to communicate as well as it should. You have to work against this explicitly. Context specification is a way to do that. It’s not yet-another playground for programmer-specific predilections.

  • http://scottbellware.com Scott Bellware

    PS: The presence of auto-mocking in a system’s tests is usually an indicator that there’s another design waiting to be realized that doesn’t require so many dependencies being introduced into a single class.

    There are design answers to this problem that don’t have to lean on tools for a resolution.

    I get that auto-mockers are fascinating tools, but programmer fascination is fraught with risk as far as programmer mental states go.

    Auto-mockers are often the drag-and-drop of the alt.net scene: they’re the tool that obscures design (especially troubled design) and the power of design to create incredible productivity.

  • http://www.lostechies.com/members/derick.bailey/default.aspx derick.bailey

    @Scott,

    good points on the “SUT” stuff. i’ve noticed a tendency to have to hunt for the definition of SUT, even in the previous versions of specs that we write for our system. however, i don’t find it enough of a problem with communicating the design and intention to be worried about it, honestly. i don’t read the implementation of the tests unless i need to know the api calls to cause the specific behavior being tested. when i need to know that level of detail for a given test, the extra 1 or 2 seconds to see the class definition for SUT isn’t an issue for me.

    on the subject of “indicator that there’s another design waiting to be realized” … i agree that it is possible, but i don’t agree that a tool like an auto mocker causes this. developers create bad design because they create bad design, not because an auto mocker let them. i have a post queued up for wednesday that addresses the problem and my opinion in more detail.

  • http://scottbellware.com Scott Bellware

    Derick,

    The automocker will cause it just as much as drag and drop causes other design problems: it obscures the better, more productive design behind tooling that creates momentary efficiencies.

    On the SUT stuff: there should be three degrees of perception in specs. You’ve got two. I should have the English descriptions, a high-level descriptive implementation in the specs, and then a level that has the details.

    I need to get the mid-level story of your specs without having to go to the deep level.

    This is a usability and user experience design issue. You’re failing to consider the user roles and make subtle and pervasive optimizations that pervasively reduces the cost of one of the most expensive usage scenarios: coding for the unfamiliar.

    You’re not making a good experience for me, the one who is unfamilliar with your code. You’re telling yourself that I can make the effort to become familiar, which is also a failure to understand the usage scenario and my role.

    In my role as an unfamiliar, I’m not interested in READING code, I’m interested in SCANNING code. Forcing me to READ into what this SUT thing is interrupts scanning and damaged the flow and productivity of the work that I’m called to do.

    By failing to code for the mid-level, you’re letting your own familiarity drive your perception of what is needed. You’re failing to see outside of the box. And THIS above all things is why programmers continue to fail to create productive user expereinces – whether with end-user interaction surfaces, or with the code that they leave behind for others.

    Those others are faced with scenarios that aren’t the scenario you personally are in when you’re writing code. When you’re writing code, you create deeper familiarity and fail to see the value of crafting for the unfamiliar. In doing this, you fail to see the cost of forcing pervasive interaction obstructions and interrupts into workflows that should be as smooth as those that you experience from your vantage as a familiar.

    You’re optimizing for yourself from within the box. No harm no foul on a one-person team, but I’d fail you right back to bootcamp if you handed me specs that didn’t allow me the mid-level scan that makes orientation blazingly productive rather than mind-numbing, disruptive, distracting, and tedious.

    Just like systems performance optimization, you have to support both read-mode and write-mode. You’re focusing on write-mode to exclusion. There’s yet another level of performance to be had be seeing beyond that.

    You don’t have to take my word for it though. Just start observing it. If you observe it for a few years, I’m dead certain that your both your awareness and your position will change. For now, it’s under the write-mode radar, which is where most usability productivity lives typically.

  • http://www.lostechies.com/members/derick.bailey/default.aspx derick.bailey

    i see your point about the unfamiliar person, and had never thought about a 3rd level of reading and understanding in the specs. i’m not sure i’ve seen the problem in real life, though, so i have a hard time agreeing with what you’re saying. i’m not dismissing the problem or saying it doesn’t exist… i’m saying i haven’t recognized it in my job / team, even if it has been present.

    which brings up the question of what are the signs? what do i look for when i’m reading someone else’s code, and when someone else is reviewing my code?

  • http://www.proace.com/blog Josh Arnold

    Good to see AutoMocking in other Ioc containers. I’m pretty fond of Fubu’s InteractionContext myself, as far as semantics are concerned.

    For example, Get() is MockFor(). Another favorite is that Get().AssertWasCalled(t => t.Something()) is simplified by setting up expectations and then doing a VerifyCallsFor().

    I’m assuming that your simplifications will make the SUT available via a property (e.g., ClassUnderTest.Something())?

  • http://www.lostechies.com/members/derick.bailey/default.aspx derick.bailey

    @josh – yeah, the next blog post is the second part of this which covers wrapping up the SUT variable with a base ContextSpecification class. I’ve also added a few more help methods since these two posts were written.

  • Peter

    Hi!
    @Scott -> can you post what you think the test should look like? Are there other artifacts that go along with the test (eg a document – diagram etc) that assist in understanding it as an “unfamiliar” ?

    Personally I use similar to the above, and although feel uncomfortable using SUT – I do use it as a programmer simplifaction.

    Its said there’s (x) phases to learning –
    1. Not knowing you don’t know.
    2. Knowing you don’t know.
    3. Learning what you don’t know
    4-x Mastering
    Finally . Teaching

    When It comes to Context spec – it looks like most of us were at phase 1 until this post. We are now at phase 2.

    Can you provide the rest for us…