Alex Rivera | Logout

Best Practices of Test Driven Development Using C# and RhinoMocks

Asked 2008-09-23T22:03:18.900
89

In order to help my team write testable code, I came up with this simple list of best practices for making our C# code base more testable. (Some of the points refer to limitations of Rhino Mocks, a mocking framework for C#, but the rules may apply more generally as well.) Does anyone have any best practices that they follow?

To maximize the testability of code, follow these rules:

  1. Write the test first, then the code. Reason: This ensures that you write testable code and that every line of code gets tests written for it.

  2. Design classes using dependency injection. Reason: You cannot mock or test what cannot be seen.

  3. Separate UI code from its behavior using Model-View-Controller or Model-View-Presenter. Reason: Allows the business logic to be tested while the parts that can't be tested (the UI) is minimized.

  4. Do not write static methods or classes. Reason: Static methods are difficult or impossible to isolate and Rhino Mocks is unable to mock them.

  5. Program off interfaces, not classes. Reason: Using interfaces clarifies the relationships between objects. An interface should define a service that an object needs from its environment. Also, interfaces can be easily mocked using Rhino Mocks and other mocking frameworks.

  6. Isolate external dependencies. Reason: Unresolved external dependencies cannot be tested.

  7. Mark as virtual the methods you intend to mock. Reason: Rhino Mocks is unable to mock non-virtual methods.

Edit
Report

2 Answers

6

Know the difference between fakes, mocks and stubs and when to use each.

Avoid over specifying interactions using mocks. This makes tests brittle.

answered 2008-09-24T05:42:26.207
4

This is a very helpful post!

I would add that it is always important to understand the Context and System Under Test (SUT). Following TDD principals to the letter is much easier when you're writing new code in an environment where existing code follows the same principals. But when you're writing new code in a non TDD legacy environment you find that your TDD efforts can quickly balloon far beyond your estimates and expectations.

For some of you, who live in an entirely academic world, timelines and delivery may not be important, but in an environment where software is money, making effective use of your TDD effort is critical.

TDD is highly subject to the Law of Diminishing Marginal Return. In short, your efforts towards TDD are increasingly valuable until you hit a point of maximum return, after which, subsequent time invested into TDD has less and less value.

I tend to believe that TDD's primary value is in boundary (blackbox) as well as in occasional whitebox testing of mission-critical areas of the system.

answered 2009-05-06T02:23:23.750

Your Answer