Logo
Windows XP
Windows Vista
Windows 7
Windows Azure
Windows Server
Windows Phone
EPL Standings
 
 
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.

NOTE

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.

Top Search -----------------
- Enabling and Customizing Pen and Touch Features
- Microsoft Visio 2010 : Creating Swimlane Diagrams
- Managing Printing : Deploying Printers Using Group Policy
- Activating and Validating Windows 7
- Managing Disks from the Command Prompt
- Microsoft Excel 2010 : Adding and Deleting a Data Series
- Networking with Windows 7 : Resolving Names to IP Addresses
- Sharing Printers, Scanners, and Fax Machines
- Microsoft Word 2010 : Saving a Document with Macros & Opening a Document with Macros
- Managing Printers Using Print Management (part 2) - Configuring Printer Driver Isolation Mode
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)
 
 
Most view of day
- Windows Server 2008 Server Core : Compressing Data with the Compact Utility
- Manage the Active Directory Domain Services Schema : Remove Attributes from the Index
- Add an InfoPath Form Web Part to a SharePoint Web Part Page
- Microsoft Systems Management Server 2003 : Defining Parent-Child Relationships (part 2) - Installing the Secondary Site Locally from the SMS CD
- Windows Server 2003 : Analyzing Traffic Using Network Monitor (part 1)
- BizTalk 2009 : Host Integration Server 2009 - Planning Your Host Integration Server Topology
- Using Windows Live Programs (part 2) - Using Windows Live Mail
Top 10
- Automating Windows 7 Installation : Customizing Images Using Deployment Image Servicing and Management (part 3) - Servicing the Operating System in an Image , Committing an Image
- Automating Windows 7 Installation : Customizing Images Using Deployment Image Servicing and Management (part 2) - Mounting an Image , Servicing Drivers in an Image
- Automating Windows 7 Installation : Customizing Images Using Deployment Image Servicing and Management (part 1) - Viewing Information about an Image with DISM
- Automating Windows 7 Installation : Applying an Image Using ImageX
- Automating Windows 7 Installation : Capturing an Image Using ImageX
- Microsoft Visio 2010 : Creating Web Pages from Visio Drawings (part 4) - Fine-tuning Web Pages and Battling Bugs - Saving a Visio Drawing as a Web Page
- Microsoft Visio 2010 : Creating Web Pages from Visio Drawings (part 3) - Fine-tuning Web Pages and Battling Bugs - Customizing Web Page Output
- Microsoft Visio 2010 : Creating Web Pages from Visio Drawings (part 2) - Exploring Visio-Generated Web Pages
- Microsoft Visio 2010 : Creating Web Pages from Visio Drawings (part 1) - Saving as Web Page
- Microsoft Visio 2010 : Sending Visio Files in Email, Saving as PDF or XPS Files
Windows XP
Windows Vista
Windows 7
Windows Azure
Windows Server
Windows Phone
2015 Camaro