Home > Programming, Unit Testing > Some TDD concepts

Some TDD concepts

Note: The tips below are for the NMock framework, but the concept might be same for other mocking frameworks. Please refer the complete article (from where I’ve taken these tips).

Traditionally, unit testing terminology has included the concepts of drivers and stubs.

A driver is a piece of software that is written with the sole purpose of accessing properties and methods on a library to test the functionality of that library. A stub is a piece of software whose only purpose is to provide the library under test with an implementation of any modules it may need to communicate with to perform its work.

fig021.gif

As illustrated in the figure, this concept translates well into practical terms. With the tools available today, you have a framework for implementing both drivers and stubs in a dynamic and flexible way. NUnit is an implementation of a driver and for stubs NMock can be used to create dynamic mock objects at run time.

The default behavior of a mock instance is to return null from every method call that returns a reference type and to return the default value from every method call that returns a value type. When dealing with methods with return values, the default behavior of the mock instance isn’t sufficient anymore. It is necessary to instruct the mock object about what to do.

Setting Expectations
The SetupResult method is still a rather blunt instrument. Any call to the configured method is answered with the same return value, no matter what parameters are used in the method call. To configure the mock instance to return appropriate values for different parameter values, the ExpectAndReturn method is used.

Consider a test where you use SetupResult. Aside from the obvious disadvantage that all calls to the same method return the same value, you don’t get much validation out of the mock object. Regardless of whether your target library called a method zero, once, or many times, you wouldn’t notice the difference. Conversely, you can use ExpectAndReturn to validate that a method was called the expected number of times, with the expected parameters, and in the expected order. With this approach, a unit test not only has the opportunity to test that a module returns the correct values, but also that it communicates with any external dependencies as designed. In fact, with some modules where most of the implementation is internal, this may very well be the only way you can perform tests in any meaningful way.

If we have no way of knowing the value of the some parameter in advance, how can we define the expectation? The answer lies in the NMock Constraint classes (the IsEqual constraint is the default).

Calling the Verify method at the end of your unit test tells the mock object that the test is over and that it should verify that all members were accessed the expected number of times. If a member happened to be accessed fewer times than expected, a VerifyException would be thrown.

To summarize the steps thus far, you set the Strict option to true at the beginning, stick with the expectation-setting methods throughout, and call the Verify method at the end of the unit test. With very little effort, you’ll have added a whole new level of validation to your unit tests.

Conclusion
In real-world software development projects, it is a rare library that doesn’t have some kind of external dependency with which it communicates frequently. When unit testing libraries, you need some kind of stub to simulate those external dependencies. NMock provides you with a valuable tool for achieving this with minimal effort. Although writing unit tests still involves work, NMock offers relief from writing, configuring, and deploying your own stub classes over and over again. Defining mock instances and their behaviors at run time also gives you a degree of flexibility and test validation you probably never would have been able to achieve if you wrote your own stubs for each external dependency.

Advertisements
Categories: Programming, Unit Testing
  1. Kevin
    May 19, 2007 at 3:59 pm

    Can you please help with understanding unit testing?
    Suppose I have a library which exposes 5 methods for any application that uses it and internally the library consists of 10 more methods.
    So when I perform unit testing, will it be sufficient to test only the exposed methods or should I also set up tests for the internal methods.
    I ask this because as an example in my case, I have an mp4 library to play mp4 files. The internal methods are somewhat complex to set up drivers for them as creating and passing the arguments of these methods seems complex.

  2. mmwaikar
    May 22, 2007 at 1:17 am

    Kevin,

    Normally we test only the publically exposed methods of an assembly.

    Since all the tests are ideally located in another assembly of its own (so for example you have an assembly named Domain, you’ll have another assembly named Domain.Tests); there is no way you can call non-public methods of the assembly to be tested.

    However, your public methods might be calling those other private / protected methods, so those will get tested automatically.

    Based on your question, I feel you may consider ‘programming to interfaces’ i.e. if a class is depending upon another classes to accomplish its work, then that class should only be referring to interfaces, from which those other classes should derive from. You may also read about Inversion of Control or Dependency Injection to improve your design.

    I also feel, any of the various Mocking frameworks like NMock or Rhino Mocks must prove helpful to you because mock objects are meant as a replacement for actual objects that are difficult to setup. I won’t be able to offer you much help on these mocking frameworks as even I am trying to use it on one of my projects.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: