Windows XP
Windows Vista
Windows 7
Windows Azure
Windows Server
Windows Phone
Windows 7

Testing Code with Visual Studio 2010 : Approaches to Unit Testing

2/3/2012 11:29:38 AM
Within the past few years, unit testing has taken on a life of its own. You're not cool if you're not doing a unit test. One of the hardest choices when creating unit tests is deciding what to test. When you examine code that you want to test, consider the following issues:
  • Public methods: Public methods are those features of your code that are exposed to the outside world. Pretty much everyone agrees you should unit test your public methods. After all, a public method is sitting there saying, "Call me."

  • Private and protected methods: Private and protected methods in your code do the work of your public methods. As a result, some people believe that testing private and protected methods is wasteful. They believe that unit testing public methods implicitly tests private and protected methods. Plus, testing private and protected methods is harder. By their nature, private and protected methods are, well, private and protected. Unlike public methods, they aren't saying, "Call me." Just the opposite is true, so you need to go out of your way to test them.

  • Interactions with other code: Unless you're writing all your application's features in a single function, chances are high your code needs to interact with other code. The very nature of unit testing, however, is that you want to test only a single unit of code. How can you do that if you have to interact with other code?

Public methods are easily tested because, by definition, you can call a public method from anywhere in your code.

People take all kinds of approaches to solve the problems of testing private methods or code that interacts with other code. One popular approach is to use software that specializes in unit testing, usually called unit testing frameworks.

Two approaches to testing code that interacts with other code are stubs and mocks.

1. Letting stubs do the tough testing

By definition, a unit test is supposed to test only one unit of code. No unit of code lives in isolation, however. Most developers work around this pesky paradox by using code stubs, which act as placeholders for units of code that the unit being tested needs to interact with.

The code stub placeholder is better than interacting with the actual units of code because each unit of code introduces a new set of variables. Instead, you can program the code stub to return a consistent set of values against which the unit can interact. Returning a consistent set of values creates predictability, which makes it easier to create tests that you can repeat.

In reality, developers who use stubs usually go ahead and test the real units of code that interact with the unit they're testing — that is, as long as it's simple to do so. For example, say that you create a Customer object with a public method called GetAddress.GetAddress returns an Address object. The Customer and AddressCustomer object to interact with the Address objects are each units of code that have their own set of unit tests. Many developers will create a test that allows their object even though the test extends beyond the unit they want to test.

When the developer encounters a set of code that is too complicated or messy to interact with a simple unit test, the developer usually creates a stub. The stub returns a set of canned values that the developer expects to get from the code.

For example, say that your Customer object has a method called UpdateAddress.UpdateAddress accepts a new address for a customer and passes that data off to an Address object. The Address object calls a service that validates the address against a valid ZIP code database. You don't want to have to deal with all that when you're testing your Customer object.

Instead of using the Address object, you create a stub that returns two possible values. If you pass a valid address, it returns the value ValidAddress. If you pass an invalid address, it returns the value InvalidAddress. So, how does the stub know what's a valid address and what's an invalid address? You specify in the stub that 123 Main Street, for example, is a valid address. Everything else is invalid. Figure 1 shows an example of a stub.

Figure 1. Use stubs any time you want to avoid messy code interactions in your testing.

2. Simplifying testing with mocking objects

Other developers believe that creating a bunch of objects and stubs is too much work. These developers use a special library to create mock objects. With mock objects — mocks — you tell the object which methods you expect it to run, how many times the methods will run, and what values to return.

For example, say that you use a mock Address object to interact with your Customer address. For your UpdateAddress test, you tell the mock Address object to call the Address object's Save method. Your test tells the mock object that you're going to send a value of 123 Main Street to the Save method and that you expect it to return a value of true. Your test also tells the mock object that you're going to send the value 123 Nowhere Boulevard and that you expect the Save method to return the value false. Figure 2 shows an example of a mock object.

Figure 2. Use mock objects to set expectations about methods called and values returned.

3. Stubs versus mocks

Deciding which method to use can be a little difficult at first glance, but several key differences exist between using mocks and stubs, based on what you want to test for. Here are some of them:

  • Mocks

    • You tell your mock objects which methods to call, how many times they'll be called by your test, and what return values you expect.

    • You create mocks for all objects with which your code interacts.

    • Mocks require a library of code to create the mock objects.

  • Stubs

    • Stubs usually return only values.

    • You create stubs only when necessary.

People who use stubs tend to test clusters of interacting objects together. For example, they might test all the code related to customers and orders together because those units of code interact.

People who use mocks, on the other hand, are more likely to take a top-down approach. They might start testing at the user interface level first and then use mock objects to mimic the behavior of business rules or data access code. They are likely to test first and code second. In other words, they use testing as a way to discover what code they still need to write to make their system work.


Using mock objects is very popular in the test-driven development (TDD) style. With TDD, you test first and code second. For more information, see the Test Driven Web site at www.testdriven.com.

4. Automating Tests with Testing Frameworks

Unit tests are often grouped so that they can be executed by a testing framework. A framework isn't necessary, but using a framework allows you to do these things:
  • Formalize unit testing.

  • Create consistency among unit tests.

  • Make automating testing easier.

  • Execute groups of tests at one time.

Frameworks are a necessity for most systems. Because unit tests are so small in nature, even a simple system has lots of tests. In most cases, using a framework to administer the tests makes sense. Unit testing frameworks exist for nearly every programming language under the sun. Popular unit testing frameworks for the .NET Framework include

  • NUnit: By far, NUnit is the most-popular testing framework around. NUnit is an open source (free) framework. However, a drawback to NUnit is that it isn't integrated into Visual Studio. Still, many folks use NUnit to manage their unit tests. You can visit the NUnit Web site at www.nunit.org.

  • NMock: Creates mock objects for use with unit tests.

  • TestDriven.NET: Integrates testing frameworks, such as NUnit, into the Visual Studio development environment. TestDriven.NET gives you the ability to access testing commands from a shortcut menu in the code editor. You can visit the TestDrive.NET Web site at www.testdriven.net.

Other -----------------
- Managing Printers Using Print Management (part 2) - Configuring Printer Driver Isolation Mode
- Managing Printers Using Print Management (part 1) - Configuring Properties of Printers, Publishing Printers in AD DS & Managing Printer Drivers
- Understanding the Print Management Console (part 2) - Configuring Default Security for Print Servers
- Understanding the Print Management Console (part 1) - Enhancements to the Print Management Console in Windows 7
- Managing Printing : How Printing Works in Windows 7
- Taking Advantage of Volume Licensing : KMS and the Client (part 2)
- Taking Advantage of Volume Licensing : KMS and the Client (part 1) - Changing the Client License Type After Installation & Postponing Activation
- Power Searches - AND, OR, and NOT searches, Date and number searches
- Microsoft Access 2010 : Exporting Information (part 2) - Exporting to XML Files
- Microsoft Access 2010 : Exporting Information (part 1)
- Microsoft Project 2010 : Saving a Set of Columns as a Table
- Microsoft Project 2010 : Adding and Removing Columns in a View
- Metadata and Power Searches : Setting Properties When You Save & Personalizing Searches
- Metadata and Power Searches : Working with File Properties
- Tracking Your Licenses with the Key Management Service (part 2) - Configuring DNS to Let KMS Clients Find the KMS Server
- Tracking Your Licenses with the Key Management Service (part 1) - Installing and Initializing KMS
- Taking Advantage of Volume Licensing : Choosing the Right Volume License Key for Windows
- Windows 7 Kernel Mode Drivers Overview and Operations : KMDF I/O Model (part 2)
- Windows 7 Kernel Mode Drivers Overview and Operations : KMDF I/O Model (part 1) - I/O Request Handler
- Windows 7 Kernel Mode Drivers Overview and Operations : KMDF Object Model
Most view of day
- Windows Server 2012 : Deploying Storage Spaces (part 1) - Understanding Storage Spaces - Concepts and terminology
- Integrating SharePoint 2013 with the Office Applications (part 1) - Microsoft Word - Writing Blog Posts
- Windows Server 2012 Group Policies and Policy Management : Policy Management Tools (part 2)
- Microsoft Exchange Server 2007 : Leveraging the Capabilities of the Outlook Web Access Client - Understanding OWA Security Features, Tips for OWA Users with Slow Access
- Customizing Windows 7 : Set Up a Desktop Slide Show
- Games and Windows 7 : Games for Windows - LIVE (part 2) - Accessing Games for Windows - LIVE from within Compatible Games
- Microsoft SQL Server 2012 : Knowing Tempdb - Troubleshooting Common Issues (part 3) - Troubleshooting Space Issues
- Maintaining Security : Restricting User Rights, Protecting Your Account
- Advanced Windows 7 Programming : Working in the Background - DEVELOPING TRIGGER-START SERVICES (part 2)
- Integrating BizTalk Server 2010 and Microsoft Dynamics CRM : Communicating from BizTalk Server to Dynamics CRM (part 4) - Configuring the BizTalk endpoints
Top 10
- MDT's Client Wizard : Package Properties
- MDT's Client Wizard : Driver Properties
- MDT's Client Wizard : Application Properties
- MDT's Client Wizard : Operating System Properties
- MDT's Client Wizard : Customizing the Deployment Share
- Windows Server 2012 : Software and User Account Control Administration (part 5) - Maintaining application integrity - Configuring run levels
- Windows Server 2012 : Software and User Account Control Administration (part 4) - Maintaining application integrity - Application access tokens
- Windows Server 2012 : Software and User Account Control Administration (part 3) - Mastering User Account Control - Configuring UAC and Admin Approval Mode
- Windows Server 2012 : Software and User Account Control Administration (part 2) - Mastering User Account Control - Elevation, prompts, and the secure desktop
- Windows Server 2012 : Software and User Account Control Administration (part 1) - Software installation essentials
Windows XP
Windows Vista
Windows 7
Windows Azure
Windows Server
Windows Phone
2015 Camaro