Unit Testing code that touches the system

Unit Tests should be fast and simple and they should not touch the system. What we mean by touching the system is any code that actually changes the file system or registry of the build system that runs the Unit Tests. Also any code that touches a remote system such as a database or a web server as these remote system should not have to exist during a Unit Test.

Unit Test Presentation (using Open Office Impress)

Question: So if your code accesses the system, how do you test this code?

Answer: You use Interface-based design and a library that can mock that interface.

Well, it is not exactly simple.

Question: What if you are using some one elses code, such as standard C# libraries in the System or Microsoft namespaces?

Answer: Imagine you need to unit test code that touches the registry. You must do the following steps:

  1. Create an interface for accessing the registry that matches Microsoft.Win32.Registry and Microsoft.Win32.RegistryKey (and you may have to create an interfaces for each object they need as well).
  2. Create a wrapper that wraps the Microsoft.Win32.Registry and Microsoft.Win32.RegistryKey (again, you have to create a wrapper for each objects they need as well).
  3. Change your production code to use the interfaces and the wrappers instead of using the system code.  For example, if dealing with the Registry this involves Microsoft.Win32.Registry and Microsoft.Win32.RegistryKey directly.Don’t use these objects directly, instead you use these objects:
    SystemInterface.Microsoft.Win32.IRegistry
    SystemInterface.Microsoft.Win32.IRegistryKey
    SystemWrapper.Microsoft.Win32.RegistryWrap
    SystemWrapper.Microsoft.Win32.RegistryKeyWrap
  4. Provide a method in your production code for replacing anywhere you use IRegistry or IRegistryKey with any object that implements the interface.
  5. In your Unit Test, mock any neededIRegistry and IRegistryKey objects.

The best solution, long-term, is that Microsoft adds interfaces to the standard .NET libraries and exposes these interfaces so a wrapper isn’t needed. If you agree, vote for this enhancement here: Implement interfaces for your objects so we don’t have use SystemWrapper.codeplex.com

However, since Microsoft hasn’t done this, you have to do it yourself. But all of this probably takes more time than your project will allow you to take, so I am going to try to get you there faster.
Step 1 and Step 2 are done for you, all you have to do is download the dll or source from here:
http://SystemWrapper.codeplex.com
Step 3 and 4 are not done for you but there are examples in the SystemWrapper project.
Step 5 can be done extremely quickly with a free (BSD Licensed) tool called RhinoMocks.
So the new steps become these:

Step 1 – Download SystemWrapper

  1. Go to http://SystemWrapper.codeplex.com and download the latest dll or the latest source.
  2. Copy the SystemInterface.dll and SystemWrapper.dll into your project (perhaps you already have a libs directory).
  3. Add references to these two dlls in your release code.
  4. Add a reference only to SystemInterface.dll in your Unit Test project.

Step 2 – Change your code to use Interfaces and Wrappers

  1. Find any place in your code where it touches the system. For example, if you touch the registry, find any place you call Registry or RegistryKey objects or reference Microsoft.Win32.
    Hint: Use the search feature in your IDE.
  2. Replace the reference with a reference to SystemWrapper and SystemInterfaces. For example, if replacingrRegistry code,
    SystemInterface.Microsoft.Win32
    SystemWrapper.Microsoft.Win32
  3. For any object that touches the system, change that object to be instantiated using the interface. For example, replace RegistryKey objects with IRegistryKey objects.

Step 3 – Allow for replacing the Interface-based objects

Create a property or function that allows you to replace the object you are mocking so you can pass in an object that is mocked.

Here is an example of how to do this when mocking a RegistryKey object using IRegistryKey.

  1. Implement the IAccessTheRegistry interface from the SystemInterface.Microsoft.Win32 namespace. Here is a sample implementation that uses lazy property injection:
            #region IAccessTheRegistry Members
    
            public IRegistryKey BaseKey
            {
                get { return _BaseKey ?? (_BaseKey = new RegistryWrap().LocalMachine); }
                internal set { _BaseKey value; }
            } private IRegistryKey _BaseKey;
    
            #endregion
    

    Notice that the setter is internal. This is because unit tests can usually access an internal method with InternalsVisibleTo. The internal set is hidden for code not in the same assembly and not included in InternalsVisibleTo.

Note: You may want to look into the “Factory” design pattern.

Step 4 – Download and Reference RhinoMocks in your Unit Test

In this step you need to download RhinoMocks and reference it with your Unit Test project. Your release project won’t need it.

  1. Go to http://hibernatingrhinos.com/open-source/rhino-mocks and download RhinoMocks.
  2. Add RhinoMocks.dll

Step 5 – Mock IRegistryKey in your Unit Test

For this, you have to understand and know how to use RhinoMocks and this takes some learning.

Instead of trying to explain this here, let’s go straight into the examples.

Examples

Forthcoming…

  1. Unit Testing Registry access with RhinoMocks and SystemWrapper
  2. Unit Testing File IO with RhinoMocks and SystemWrapper

Return to C# Unit Test Tutorial

2 Comments

  1. Mohammad Imadoddin says:

    But these situation never(extremely rarely) occurs as we can trust registries and all.

Leave a Reply

How to post code in comments?