Pages

Wednesday, August 31, 2016

Catching Up on Coding - TDD Part 3

I’ve been a software developer for twenty years, but am behind in some skills. This series chronicles my self-improvement.

It turns out that unit testing exercises a lot of coding methods for more maintainable code. Some methods involve deception, so who better to inspire us than our “Butch Cassidy/Sundance Kid” knockoffs from 70s show Alias Smith and Jones? The difference is, I’m not trying to “get out of this business.”

Previously on CUOC: TDD Part 2
Next Episode: Claims-Based Identity Part 1

 

Teaser

Unit testing benefits from mocking and Inversion of Control. I’d argue that it’s hard to effectively unit test without these techniques. Parts one and two of this TDD series used hand-crafted mocking and IoC. Today, we’ll redo some tests using 3rd party tools/frameworks.

Act 1 – Choosing the Tools

I researched what developers are recommending for mocking and IoC. Of course, opinions abound, but in the end I came to a few conclusions.

Mocking

  • No one recommends Rhino Mocks anymore. It appears to be a mostly dead project.
  • Moq is still used, but is falling out of favor.
  • Developers like NSubstitute and FakeItEasy.
  • NSubstitute has a more concise API. FakeItEasy is more natural language and less ambiguous.
  • My reaction to seeing them side-by-side is that I like FIE’s syntax more. I like tests that are immediately easy to understand.
  • But I’m a little put off by the verbosity, so I’ll try NSubstitute first.

References

C# Test Mocking Frameworks

NSubstitute: A Refreshingly Simple Mocking Framework for Unit Tests

Mocking: why we picked NSubstitute

Easy Mocking with FakeItEasy

IoC

  • Ninject is the most popular, and has the worst performance (though some developers argue that IoC container performance doesn’t matter).
  • Unity is supported (for now) by Microsoft, but people have complained about some limitations.
  • StructureMap, Autofac, and Simple Injector remain as the choices. Based on a few reviews—but mostly gut instinct—I’m going to use Simple Injector. (Autofac would be my second choice.)

References

IoC Container Benchmark – Performance comparison

Inversion of Control Containers Basic Comparison

IoC Battle in 2015 results: Using Ninject – think again!

Generic variance in DI containers

Simple Injector Migration Guide <-I love that they include how to migrate away from their product. Also serves as a coding comparison.

Act 2 – Making a Mockery of Testing

Install NSubstitute

  1. Install the package into the unit test project using NuGet.
  2. After installation, a nice readme.txt file opens. Read it.

Replace a Previous Test

In my previous tests, I created my own mock Registry wrappers from IRegistryWrapper and IRegistryMockWrapper. These are interfaces I created to allow Inversion of Control of the Registry. IRegistryWrapper looks like this

    public interface IRegistryWrapper
    {
        object GetValue(string keyName, string valueName, object defaultValue);
        void SetValue(string keyName, string valueName, object value, RegistryValueKind valueKind);
    }

the hand-crafted mock looks like this

    class RegistryMock : IRegistryWrapper
    {
        public object GetValue(string keyName, string valueName, object defaultValue)
        {
            //this may become cumbersome, but for now specify some return values
            switch (keyName)
            {
                case @"HKEY_LOCAL_MACHINE\SOFTWARE\EduAgent":
                    if (valueName == "Version") return defaultValue;
                    break;
            }
            throw new Exception("Invalid keyName");
        }

        public void SetValue(string keyName, string valueName, object value, RegistryValueKind valueKind)
        {
            throw new NotImplementedException();
        }
    }

here’s the unit test

    public class RegistryService_GetRegistryKeyValue_Should
    {
        IRegistryWrapper _registry = new RegistryMock();
        IRegistryKeyWrapper _registryKey = new RegistryKeyMock();

        [Fact]
        public void ReturnNullConstantTextIfValueIsMissing()
        {
            var service = new RegistryService(_registry, _registryKey);
            var result = service.GetRegistryKeyValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\EduAgent", "Version");
            Assert.Equal(result, service.NoValue);
        }
    }

and finally, here's the RegistryService method that passes the test

        public string GetRegistryKeyValue(string keyName, string valueName)
        {
            try
            {
                //value will be null if no value found, and the default value if the key is missing. But we only care that there's no value.
                //Null can't be returned to the client. Don't return empty, since that's ambigious (did the key exist?).
                //Return a magic string.
                object value = _registry.GetValue(keyName, valueName, null); //guarantees null if no value or missing key.
                return value != null ? value.ToString() : NoValue;

            }
            catch (Exception ex)
            {
                return "Error attempting keyName '" + keyName + "' and valueName '" + valueName + "'\r\n" + ex.GetBaseException().Message;
            }
        }

All I’m going to do is refactor the test so that I use NSubstitute instead of my own mocks. I’ll need a mock for IRegistryKeyWrapper because the class expects it, but I won’t set any behavior on it.

Note: remember to add “using NSubstitute;”

In my hand-crafted mock, I specified return values based on the arguments to GetValue, and otherwise threw an exception. For my unit test, I need to do something similar. Here’s my first attempt, and it does indeed pass.

            
            var registry = Substitute.For<IRegistryWrapper>();
            var registryKey = Substitute.For<IRegistryKeyWrapper>();
            //Registry.GetValue will return null if the valueName doesn't exist.
            registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\EduAgent", "Version", null).Returns(null);
            var service = new RegistryService(registry, registryKey);
            var result = service.GetRegistryKeyValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\EduAgent", "Version");
            Assert.Equal(result, service.NoValue);

The problem is (or seems to be), if I change the substitute's argument "Version" to "Blamo", the test still passes. This is happening because given an unknown argument the method will still return null. I need to tell the substitute that it should only return null if it gets the right arguments.

Or do I?

No, I don’t. I’m attempting to give my mock too much behavior. I only want the mocked Registry to pretend that the value was missing and return null. Elsewhere I’ll test the behavior if the value exists. My hand-crafted mock was eventually going to give me trouble because it was doing too much and it wasn’t really behaving like the Registry class.

The Heart of Mocking

The method I’m testing happens to be  a good one for getting at the essence of mocking. RegistryService.GetValue is almost a pass-through to Registry.GetValue. But, it has its own behavior and is supposed to call Registry.GetValue.

As the developer and tester, I know three things:

  1. How external dependencies behave (Microsoft.Win32.Registry).
  2. How my test behaves.
  3. What’s in my method.

That last one is the problem. I know my method calls Registry.GetValue(), because I wrote it. But that’s a serious mental mistake when it comes to the test. I need to write my tests, whether before or after, as if I knew nothing about the method’s code. I should pretend the only things I know about the method are:

  1. The parameters it’s called with.
  2. The dependencies it has.
  3. The result when it’s called with particular values.

In short, my method is a black box. It could be empty, for all I know. That’s why TDD starts with an empty method, so that it fails first. If it succeeds when empty, that’s a problem. When my method has a dependency, I need to only mock up what that dependency will do if it’s called with the expected value.

But, I mustn’t assume the mocked dependency has been called at all.

So, here’s how my test should look.

            //Arrange
            var registry = Substitute.For<IRegistryWrapper>();
            var registryKey = Substitute.For<IRegistryKeyWrapper>();
            //Registry.GetValue will return null if the valueName doesn't exist.
            registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\EduAgent", "Version", null).Returns(null);
            var service = new RegistryService(registry, registryKey);
            //Act
            var result = service.GetRegistryKeyValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\EduAgent", "Version");
            //Assert
            //First, make sure the mocked Registry was called at least once. Otherwise, we might have a false positive.
            registry.Received().GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\EduAgent", "Version", null);
            //Now make sure we got back the expected value from our method.
            Assert.Equal(result, service.NoValue);

To sum up, some key lessons of unit testing are:

  1. Treat the method under test as a black box.
  2. Test behaviors of the method, not its dependencies.
  3. Verify mocked dependencies are called.

A mocking framework gives more value than just controlling return values. It lets you know that your dependencies are being used the way you expect.

Act 3 – Ouch! Injecting Dependencies

  1. Interfaces are used in production code to make it easier to inject dependencies.
  2. Mocking frameworks are used in unit testing code to control injected dependencies.
  3. IoC containers are used in production code to manage injected dependencies.

For the first two, see Act 2, above.

I don’t have  to use an IoC container. I can write code like this:

//pass the live registry wrappers
RegistryService service = new RegistryService(new RegistryWrapper(), new RegistryKeyWrapper());

I could also let my class have default dependencies. This might be OK, as long as the caller knows what to expect. It would be considered "convention over configuration."

    public class RegistryService
    {
        private IRegistryWrapper _registry;
        private IRegistryKeyWrapper _registryKey;

        public RegistryService()
        {
            _registry = new RegistryWrapper();
            _registryKey = new RegistryKeyWrapper();
        }
        public RegistryService(IRegistryWrapper registry, IRegistryKeyWrapper key)
        {
            _registry = registry;
            _registryKey = key;
        }
        ...
    }

    //usage, by default uses the Windows Registry.
    var service = new RegistryService();

For simple cases, using an IoC is overkill. In fact, I would say:

Don’t use an IoC container unless you have to.

When do you “have to”?

  • Where there are lots of dependencies.
  • When you have lots of nested dependencies.
  • When you want your dependency initialization to be in one place.

There are probably other reasons, but those will do for now.

Install Simple Injector

  1. Get it from NuGet, install to the project that’s injecting the dependencies.

Injection!

First, I prepare my RegistryService class for dependency injection.

    public class RegistryService
    {
        private IRegistryWrapper _registry;
        private IRegistryKeyWrapper _registryKey;

        public RegistryService(IRegistryWrapper registry, IRegistryKeyWrapper key)
        {
            _registry = registry;
            _registryKey = key;
        }

My Windows service, EduAgent, is calling the RegistryService, which is in a separate DLL. I want all my dependencies initialized once, in one place. The service’s Main method is the starting point. But, you know what, to make it easier for another developer, I’ll create a class called DependencyInjection, which we’ll call from Main. That makes it pretty clear where the dependencies are maintained, and how.

All we’re doing here is saying “if I request from ‘container’ a type of IRegistryWrapper, give me an instance of the class RegistryWrapper.”

    public static class DependencyInjection
    {
        public static Container container;
        public static void InitializeDependencies()
        {
            //create container
            container = new Container();
            //register interfaces
            container.Register<IRegistryWrapper, RegistryWrapper>();
            container.Register<IRegistryKeyWrapper, RegistryKeyWrapper>();
            //register concrete types
            container.Register<RegistryService>();
            //optionally verify
            container.Verify();
        }
    }

I initialize the dependencies.

    static class Program
    {
        /// 
        /// The main entry point for the application.
        /// 
        static void Main()
        {
            DependencyInjection.InitializeDependencies();
            ServiceBase[] ServicesToRun;
            ...

Notice that during initialization, I’m also registering the concrete type RegistryService. I’m doing this so that I can request an instance of RegistryService without passing any constructor arguments. The container knows what to pass in on my behalf.

   //pass the live registry wrappers, which are auto-wired by Simple Injector
   RegistryService service = DependencyInjection.container.GetInstance<RegistryService>();

This is the same as if I had done this:

   RegistryService service = new RegistryService(new RegistryWrapper(), new RegistryKeyWrapper());

But by using an IoC container, if I use a different (again, fictitious) registry provider, I only need to set it in one place: InitializeDependencies.

Tag

There’s a lot more to mocking and dependency injection than the above samples show. I ran into a pretty significant problem because my original IRegistryKeyWrapper included IDisposable, which plays hell with dependency injection.

Lesson: Sometimes these tools add complications. But other times, they reveal problems in your code.

On the subject of complications, one of the stars of Alias Smith and Jones killed himself during the first season. He suffered from depression and alcoholism. To this day, that makes me sad. Pete Duel, I miss what you could have done.

image

Wednesday, August 24, 2016

Catching Up on Coding - TDD Part 2

I’ve been a software developer for twenty years, but am behind in some skills. This series chronicles my self-improvement.

Taking a cue from the 70s and its badass fonts, my Fantastic Journey is traveling from skill to skill, trying to escape every software engineer’s Bermuda Triangle: obsolescence. I don’t have Jared Martin’s Sonic Energizer to focus my thoughts and manipulate matter. All I can do is listen to the groovy theme music.

Previously on CUOC: TDD Part 1
Next Episode: TDD Part 3

 

 

Teaser

It’s one thing to practice TDD from the start. It’s another to take legacy code that you wrote and create unit tests for it. My EduAgent project includes a client service that processes requests to update the registry.

Looking at my code, I right away see my first stumbling block: the purpose of the code is changing the registry. For testing, this means:

  • Affecting the registry of whatever computer the tests run on.
  • Guaranteeing each test starts with a clean environment. What does this mean for parallel testing?
  • Guaranteeing the registry returns to its original state, regardless of test results.
  • Not breaking the computer.

These are characteristics of integration/functional tests, not unit tests. Should I mock the registry classes to deal with this code?

object value = Registry.GetValue(keyName, valueName, null);

If I do—if I can—am I really testing anything? Or am I creating fake conditions that assure the test will pass? There’s a danger, in unit testing, of creating tests that don’t actually test the method: they “test” a mock that will always return the expected value.

Act 1 – What I Can Test, What I Should

The purpose of mocks is to allow the unit test to focus on what it can test, and ignore what can corrupt the test—assuming what can corrupts the test isn’t exactly what should be tested!

A classic, challenging example is methods that access a database. I don’t want to test if I can access the database. I want to test what I’m doing with the data. For example, consider this class method.

public class EmployeeInfoService
{
	IEmployeeDbContext _db;
	public EmployeeInfoService(IEmployeeDbContext db) { _db = db; }
	public List GetAverageHourlyPay(int[] employeeIds)
	{
		return from stats in _db.PayStubs
		//...a bunch of code that gets data and calculates the hourly pay by doing this:
                // stats.Hours / stats.Amount
		;
	}
}

I don’t care, in the test I’m about to write, if I can access the database, or if the database is returning the right data, or breaks when I hand it a list of EmployeeIds. All I care about is whether the method properly does the math given specific numbers. So, I’d mock the EmployeeDbContext and fabricate the numbers.

	[Fact]
	public void EmployeeInfoService_GetAverageHourlyPay_Should_Correctly_Calculate()
	{
		var db = new MockEmployeeDbContext();
		//...add a bunch of test data to the mock, then pass it to service
		var service = new EmployeeInfoService(db);
		var list = service.GetAverageHourlyPay(new int[] { 1, 2, 3 });
		Assert.Equals(23.34, list[0].AverageHourlyPay);
		Assert.Equals(17.98, list[1].AverageHourlyPay);
	}

Contrast that to this method.

	public string[] GetEmployeeNames()
	{      return _db.Employees.Select(a => a.Name).ToArray();
	}

Is there any reason to create a unit test for this method? I don’t think so. The test would look something like this.

	[Fact]
	public void EmployeeInfoService_GetEmployeeNames_Should_Return_A_List_Of_Names()
	{
		var db = new MockEmployeeDbContext();
		//...add a bunch of mock Employees with names, then pass to service
		var service = new EmployeeInfoService(db);
		var list = service.GetEmployeeNames();
		Assert.True(list.Contains("Varian"));
	}

This gets us nothing. All we did was test that our mocking framework works. So…

Lesson 1: Be sure you’re testing something that can fail.

Act 2 – The Simple Test

For my RegistryService class, I have a different problem as stated above. Can I even mock the .Net Registry class? We’ll look at that shortly. For right now, I’ll evaluate all the methods and see which ones I can test without mocking. Here’s the complete list:

  • ProcessRequest
  • GetRegistryKeyValue
  • GetRegistryValueKind
  • SetRegistryKeyValue
  • DeleteRegistryKey
  • DeleteRegistryValue
  • OpenSubKey64
  • ParseRegistryHive
  • NotifyAppsOfRegistryChange

Of all these, just one doesn’t require using registry data: ParseRegistryHive. The method’s purpose is to return the hive enum given a string.

        public static RegistryHive ParseRegistryHive(string hiveName)
        {
            if (hiveName.ToUpper() == "HKEY_CLASSES_ROOT") { return RegistryHive.ClassesRoot; }
            else if (hiveName.ToUpper() == "HKEY_CURRENT_USER") { return RegistryHive.CurrentUser; }
            else if (hiveName.ToUpper() == "HKEY_LOCAL_MACHINE") { return RegistryHive.LocalMachine; }
            else if (hiveName.ToUpper() == "HKEY_USERS") { return RegistryHive.Users; }
            else if (hiveName.ToUpper() == "HKEY_CURRENT_CONFIG") { return RegistryHive.CurrentConfig; }
            //last chance, will throw error if invalid
            else return (RegistryHive)Enum.Parse(typeof(RegistryHive), hiveName);
        }

I’m using xUnit.net for my unit testing. xUnit’s Theories are pretty nice, allowing testing sets of data. My tests verify that the method throws errors—or doesn’t—appropriately, and also that it returns the correct hive. I wrote a note to myself about that last one, summed up as:

Lesson 2: Don’t copy/paste any code from your test into the method you’re testing. What if your test has a bug?

    public class RegistryService_ParseRegistryHive_Should
    {
        [Theory]
        [InlineData("HKEY_CLASSES_ROOT")]
        [InlineData("HKEY_CURRENT_USER")]
        [InlineData("HKEY_LOCAL_MACHINE")]
        [InlineData("HKEY_USERS")]
        [InlineData("HKEY_CURRENT_CONFIG")]
        [InlineData("hkey_current_config")]
        public void NotThrowErrorWithValidHive(string name)
        {
            var hive = RegistryService.ParseRegistryHive(name);
        }

        [Theory]
        [InlineData("HKEY_CLASSES_ROOT")]
        [InlineData("HKEY_CURRENT_USER")]
        [InlineData("HKEY_LOCAL_MACHINE")]
        [InlineData("HKEY_USERS")]
        [InlineData("HKEY_CURRENT_CONFIG")]
        public void ReturnCorrectEnumWithValidHive(string name)
        {
            //This basically reproduces the method code. Need to NOT copy/paste from method, but
            //instead rewrite. In TDD, would NOT copy/paste from the test, otherwise there's a danger
            //the test duplicates a wrong condition.
            var hive = RegistryService.ParseRegistryHive(name);
            switch (name)
            {
                case "HKEY_CLASSES_ROOT":
                    Assert.True(hive == Microsoft.Win32.RegistryHive.ClassesRoot);
                    break;
                case "HKEY_CURRENT_USER":
                    Assert.True(hive == Microsoft.Win32.RegistryHive.CurrentUser);
                    break;
                case "HKEY_LOCAL_MACHINE":
                    Assert.True(hive == Microsoft.Win32.RegistryHive.LocalMachine);
                    break;
                case "HKEY_USERS":
                    Assert.True(hive == Microsoft.Win32.RegistryHive.Users);
                    break;
                case "HKEY_CURRENT_CONFIG":
                    Assert.True(hive == Microsoft.Win32.RegistryHive.CurrentConfig);
                    break;
                default:
                    Assert.True(false,name + " didn't return a valid hive. Hive enum returned was " + hive);
                    break;
            }
        }

        [Theory]
        [InlineData("fail")]
        [InlineData("")]
        public void ThrowErrorWithInvalidHive(string name)
        {
            Assert.Throws(() =>  RegistryService.ParseRegistryHive(name));
        }
    }

Act 3 – Testing the Difficult: Mock it, or . . .

I’ve been putting it off long enough. What about the rest of the methods? You know, the ones that could completely screw up my registry?

First, which methods do testable work? Some of them are just wrappers so that I can get back a better error message, for example:

        public static void SetRegistryKeyValue(string keyName, string valueName, string value, RegistryValueKind dataType = RegistryValueKind.String)
        {
            try
            {
                Registry.SetValue(keyName, valueName, value, dataType);
            }
            catch (Exception ex)
            {
                throw new Exception("Error setting registry value keyName '" + keyName + "', valueName '" + valueName + ", value '" + value + "'\r\n" + ex.GetBaseException().Message);
            }
        }

Do I need to test this? Well, I’d like to test that I get back the right exception, so…hmm. OK, let’s see if anyone has mocked the registry.

In the last bullet, I quote from an excellent Stack Overflow response on the subject. In fact, here are two comments.

The research tells me I have two choices:

  1. Mock the concrete Registry class
  2. Use a wrapper around the Registry class

I looked at the Prig example. Whew! That’s a lot of setup! And I’m not prepared to pay for TypeMock or JustMock, though I expect they’re excellent.

This means wrapping the Registry class. Before I try out SystemWrapper, I’m going to create my own wrapper. I want to understand what’s involved. (This is self-education, after all!) The methods I’m using are:

Registry.GetValue
Registry.SetValue
RegistryKey.GetValueKind
RegistryKey.DeleteSubKey
RegistryKey.DeleteValue
RegistryKey.OpenBaseKey
RegistryKey.OpenBaseKey.OpenSubKey

All right, boys! Wrap…That…Code!!!

I had to rethink my whole approach to my RegistryService class, which consumes the Microsoft.Win32.Registry. Originally I wrote it as a static class, since it didn’t need to be instantiated. But this class now could depend on different “registry providers.” I want to protect the class from being misused. A static SetRegistryProvider method won’t work, because of the danger that in production one caller sets it one way and another sets it differently. It’s the same as if a class could use more than one database back end; you wouldn’t make it static. The solution was to remove static, and make the class entirely instance-able.

Moving on, the Registry wrapper is pretty straight forward. The oddity is that I’m wrapping a static class in an instance.

    public interface IRegistryWrapper
    {
        object GetValue(string keyName, string valueName, object defaultValue);
        void SetValue(string keyName, string valueName, object value, RegistryValueKind valueKind);
    }

    public class RegistryWrapper : IRegistryWrapper
    {
        public object GetValue(string keyName, string valueName, object defaultValue)
        {
            return Registry.GetValue(keyName, valueName, defaultValue);
        }

        public void SetValue(string keyName, string valueName, object value, RegistryValueKind valueKind)
        {
            Registry.SetValue(keyName, valueName, value, valueKind);
        }
    }

The RegistryKey wrapper presented a challenge. The constructor for RegistryKey is private. You cannot create an instance of RegistryKey this way:

RegistryKey key = new RegistryKey(); //this won't compile

Instead, instances are created using the static method OpenBaseKey().

RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64);

My abstraction needs to be clear, I want to create an interface, but interfaces can’t have static members.

A base key is required for RegistryKey to function, therefore it’s required for my wrapper to function. But the RegistryService class, which uses RegistryKey, encapsulates which base key will be used; each method could instantiate its own RegistryKey with different base keys. For example:

public void DeletePluginVersionValue(string id)
{
    //_registryKey was injected via the constructor
    RegistryKey basekey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default);
    using (RegistryKey key = basekey.OpenSubKey(@"SOFTWARE\EduAgent\RegistryPlugin", false))
    {
        key.DeleteValue("Value");
        key.Close();
    }
}

My abstracted class is going to work similarly.

public void DeletePluginVersionValue(string id)
{
    //_registryKey was injected via the constructor
    IRegistryKeyWrapper basekey = _registryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default);
    using (IRegistryKeyWrapper key = basekey.OpenSubKey(@"SOFTWARE\EduAgent\RegistryPlugin",false))
    {
        key.DeleteValue("Value");
        key.Close();
    }
}

But for testing, I need to pass in a non-null class instance that implements an interface, but does not have a base class yet. I can’t do this:

    public interface IRegistryKeyWrapper: IDisposable
    {
        IRegistryKeyWrapper OpenSubKey(string name, bool writable);
        //originally static
        IRegistryKeyWrapper OpenBaseKey(RegistryHive hKey, RegistryView view);
    }

    public class RegistryKeyWrapper : IRegistryKeyWrapper
    {
        private RegistryKey _baseKey;
        private RegistryKeyWrapper(RegistryKey key)
        {
            _baseKey = key;
        }
        //etc.

Why not? Follow along.

The RegistryService constructor:

    public class RegistryService
    {
        private IRegistryWrapper _registry;
        private IRegistryKeyWrapper _registryKey;

        public RegistryService(IRegistryWrapper registry, IRegistryKeyWrapper key)
        {
            _registry = registry;
            _registryKey = key;
        }

Using the RegistryService:

//this won't compile; RegistryKeyWrapper requires base key!
RegistryService service = new RegistryService(new RegistryWrapper(), new RegistryKeyWrapper());

I need to be able to create a new RegistryKeyWrapper(), but my live registry wrapper right now requires an actual registry base key. The (unfortunate) solution is to allow the user to create an instance of the class that can’t work.

    public class RegistryKeyWrapper : IRegistryKeyWrapper
    {
        private RegistryKey _baseKey;

        /// 
        /// Note the class can't be used until instantiated using OpenBaseKey or setting to another RegistryKeyWrapper.
        /// This constructor is here to allow an instance to be passed via dependency injection.
        /// 
        public RegistryKeyWrapper() { }

        private RegistryKeyWrapper(RegistryKey key)
        {
            _baseKey = key;
        }

In the RegistryService example, above, if the user were to use _registryKey immediately, without setting it using OpeBaseKey, it would fail because the private variable _baseKey has not been set.

I wouldn’t call this ideal, but it does allow us to test the class.

EDIT 8/31/16
-------------------------------------------------------------

Not only is it not ideal, but it’s not even good. What I’m trying to do is wrap RegistryKey in a pass-through manner. But that’s a mistake, because it implements IDisposable and in my wrapper I should not implement IDisposable.

In a later post, I’ll explain how I rewrote my RegistryKey wrapper in a better way. It doesn’t affect the validity of the info in this post.

-------------------------------------------------------------

First, I’ll fix up my previous tests for ParseRegistryHive that relied on Registry. In my unit test project I create the mock classes. At this point, I don’t even make the classes work, since ParseRegistryHive doesn’t depend on any methods.

    class RegistryMock : IRegistryWrapper
    {
        public object GetValue(string keyName, string valueName, object defaultValue)
        {
            throw new NotImplementedException();
        }

        public void SetValue(string keyName, string valueName, object value, RegistryValueKind valueKind)
        {
            throw new NotImplementedException();
        }
    }

And update a test to use the new service, passing in the mocks.

        IRegistryWrapper _registry = new RegistryMock();
        IRegistryKeyWrapper _registryKey = new RegistryKeyMock();
                
        [Theory]
        [InlineData("HKEY_CLASSES_ROOT")]
        [InlineData("HKEY_CURRENT_USER")]
        [InlineData("HKEY_LOCAL_MACHINE")]
        [InlineData("HKEY_USERS")]
        [InlineData("HKEY_CURRENT_CONFIG")]
        [InlineData("hkey_current_config")]
        public void NotThrowErrorWithValidHive(string name)
        {
            var service = new RegistryService(_registry, _registryKey);
            var hive = service.ParseRegistryHive(name);
        }

Now, create a test for the RegistryMock.

    public class RegistryService_GetRegistryKeyValue_Should
    {
        IRegistryWrapper _registry = new RegistryMock();
        IRegistryKeyWrapper _registryKey = new RegistryKeyMock();

        [Fact]
        public void ReturnNullConstantTextIfValueIsMissing()
        {
            var service = new RegistryService(_registry, _registryKey);
            var result = service.GetRegistryKeyValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\EduAgent", "Version");
            Assert.Equal(result, service.NoValue);
        }
    }

Which requires RegistryMock.GetValue to be implemented:

    class RegistryMock : IRegistryWrapper
    {
        public object GetValue(string keyName, string valueName, object defaultValue)
        {
            //this may become cumbersome, but for now specify some return values
            switch (keyName)
            {
                case @"HKEY_LOCAL_MACHINE\SOFTWARE\EduAgent":
                    if (valueName == "Version") return defaultValue;
                    break;
            }
            throw new Exception("Invalid keyName");
        }

Running the test, it passes.

Next up, using the RegistryKeyMock. Here’s the test:

    public class RegistryService_OpenSubKey64_Should
    {
        IRegistryWrapper _registry = new RegistryMock();
        IRegistryKeyWrapper _registryKey = new RegistryKeyMock();

        [Fact]
        public void ThrowExceptionWhenUsingInvalidKey()
        {
            var service = new RegistryService(_registry, _registryKey);
            var ex = Assert.Throws(() => service.OpenSubKey64(@"HKEY_LOCAL_MACHINE\SOFTWARE\EduAgentMissing"));
            Assert.Equal("Error opening subkey 'HKEY_LOCAL_MACHINE\\SOFTWARE\\EduAgentMissing'. Operation returned null.", ex.Message);
        }
    }

Here are the relevant methods I had to implement. This one was kind of tricky because I have to set properties that are read only. I’m making use of the latest C# language features to set the value of read only properties in the constructor. I also needed a helper method to return the string representation of a hive name.

    public class RegistryKeyMock : IRegistryKeyWrapper
    {
        public RegistryKeyMock() { }
        public RegistryKeyMock(string name, int subKeyCount, int valueCount, RegistryView view)
        {
            Name = name;
            SubKeyCount = subKeyCount;
            ValueCount = valueCount;
            View = view;
        }

        public string Name { get; }
        public int SubKeyCount { get; }
        public int ValueCount { get; }
        public RegistryView View { get; }

        public IRegistryKeyWrapper OpenBaseKey(RegistryHive hKey, RegistryView view)
        {
            return new RegistryKeyMock(HiveToString(hKey), 10, 10, view);
        }

        public IRegistryKeyWrapper OpenSubKey(string name, bool writable)
        {
            if (name == @"SOFTWARE\EduAgentMissing")
                return null;
            return new RegistryKeyMock(Name + "\\" + name, SubKeyCount, ValueCount, View);
        }

        private string HiveToString(RegistryHive hive)
        {
            string key = "HKEY_";
            if (hive == RegistryHive.ClassesRoot) return key + "CLASSES_ROOT";
            if (hive == RegistryHive.CurrentConfig) return key + "CURRENT_CONFIG";
            if (hive == RegistryHive.CurrentUser) return key + "CURRENT_USER";
            if (hive == RegistryHive.LocalMachine) return key + "LOCAL_MACHINE";
            if (hive == RegistryHive.Users) return key + "USERS";
            return "";
        }
    }

Test it, it passes, love those green lights!

Tag

This was like a special made-for-TV movie of Fantastic Journey. With all the stuff I’ve done, what haven’t I? Well, there are two big ones:

But I’m leaving those for a future post. Otherwise, like our intrepid explorers, I’ll be canceled and never get back to my own time and place.

Thursday, August 18, 2016

Catching Up on Coding - TDD Part 1

I’ve been a software developer for twenty years, but am behind in some skills. This series chronicles my self-improvement.

There are some pretty high-tech tools out there, but nothing that matches the inspiration provided in the 70s TV show “Search” (originally “Probe”). I don’t have Burgess Meredith, a Probe Scanner or a catchy theme song to help me out, so, like Hugh O’Brian, I’ll have to rely on my wits and Test Driven Development (TDD).

Previously, on CUOC: The Syllabus.
Next Episode: TDD Part 2

 

Teaser

I’m not truly new to TDD. I wrote a (not very good) unit testing framework for Visual Basic 6 back in 2000. I’ve used TDD in professional projects. But now it’s time to make it a habit. To do that, I need a crash coarse, then retrofit my EduAgent code (applying “Test Eventually Development”) before writing new code.

Act 1 – The Elemental Education

Let’s give primary credit where it’s due. I read James Bender’s blog 30 Days of TDD. Bender’s series is very good overall. He does—frustratingly--have sloppy grammar and punctuation errors in every post. But his information is otherwise clear and solid. In fact, his description of SOLID is one of the best I’ve read. Thanks, James!

But first things first: what problem was TDD trying to solve?

Programmers, being human, don’t like to test our work. Most of us find it as hard as writers self-editing or composers checking for wrong notes. We like QA departments because they find our (careless) mistakes for us. We pretend to hate QA, because we pretend we’re egotistical Greek gods incapable of flaw.

Unit testing frameworks allowed testing the public interface of our classes. But that wasn’t enough. Kent Beck encouraged an upside-down approach to writing code, where we write a failing test first, then make it pass. This naturally builds up a library of tests that can be run quickly, reducing the chance of new features breaking the application, and building developer confidence. It also turned out that creating easily testable methods led to generally more maintainable code. Thus, some people revised TDD to mean test-driven design.

What are the elements of TDD? What’s needed to build testable code?

Elements

  • Test framework such as NUnit and xUnit.net
  • Test runner, for executing tests and viewing results.
  • Dependency Inversion (depend on abstractions) and Dependency Injection (decouple dependencies). Both are covered pretty well in this article.
  • Mocking (control results from external resources, such as databases)
  • Refactoring (improving code maintainability without changing the public interface)

Act 2 – Some Code, a Test

Here’s a simple example of TDD, creating code that needs to be tested, and problems with it. I’m using xUnit.Net because I’ve always liked it. I won’t go into how to set up your environment; you can learn that at Getting Started with xUnit.net. However, I do have three tips for using the VS Test Runner (which you open via Test > Windows > Test Explorer).

  • Tear off the Test Explorer into its own window, so that you can easily resize and see all the tests.
    image
  • Group the test results by class
    image
  • In your unit test project, add an app.config file with the following setting. This causes the result to display only the method name instead of the fully qualified name.
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>
        <add key="xunit.methodDisplay" value="method"/>
      </appSettings>
    </configuration>
    

Our contrived application helps teachers grade coursework. We’re writing a class dealing with the coursework, and we’re consuming a third-party service—GradeMark—that returns a grade. One challenge, however, is we don’t control the grade that GradeMark returns given a set of scores. It depends on however the school has configured it. So, today 90% or higher could be an “A,” but tomorrow 93% or higher could be an “A.”

Our CourseWork class will have two methods. One that returns a percentage, and the other that returns a grade message. The grade in the message will come from the GradeMark “service,” and we’ll eventually have to mock that service.

First, in CourseWork, create a GetPercent function that doesn’t work. We want a failing test.

    public class CourseWork
    {
        public decimal GetPercent(decimal actual, decimal maximum)
        {
            throw new NotImplementedException();
        }
    }

In the unit tests project, create the test. Notice the naming convention I’m using along with nested classes; this will help make the test results readable. There are lots of naming conventions out there. Consistency and clarity are the big deals.

Our first test checks that we get back a percent in a particular format. We want “a hundred percent” to return as 100.00.

    public class BasicTdd
    {
        public class CourseWork_GetPercent_Should
        {
            [Fact]
            public void Return100PercentAs100PointZero()
            {
                var cw = new CourseWork();
                decimal percent = cw.GetPercent(100, 100);
                Assert.Equal(100m, percent);
            }
        }
    }

Run it and it fails.

image

Write enough code for the test to pass.

        public decimal GetPercent(decimal actual, decimal maximum)
        {
            decimal result = (actual / maximum) * 100m;
            return result;
        }

Run the test and it passes.

image

Our next test will check if the result is rounded. This does not depend on the first test; they could be run in reverse order.

    public class BasicTdd
    {
        public class CourseWork_GetPercent_Should
        {
            [Fact]
            public void RoundPercentToTwoDecimalPlaces()
            {
                var cw = new CourseWork();
                var percent = cw.GetPercent(1, 7);
                var roundedPercent = Math.Round(percent, 2);
                Assert.Equal(roundedPercent, percent);
            }
        }
    }

Run it, and it fails.

image

Update the code to make it pass.

        public decimal GetPercent(decimal actual, decimal maximum)
        {
            decimal result = Math.Round((actual / maximum) * 100m,2);
            return result;
        }

image

That’s enough to demonstrate a basic test. Now, on to something that will require mocking.

Act 3 – Mocu-mental Grades

Let’s create a class that represents our fictional third-party service, GradeMark. Remember, it returns a grade when supplied a percent, but we can’t depend on what that grade will be. For our dummy service, we won’t even use the percent parameter.

    public class GradeMarkService
    {
        public string GetGrade(decimal percent)
        {
            var rnd = new Random();
            int code = rnd.Next(65, 70);
            return ((char)code).ToString();
        }
    }

We’re just returning a random letter A-D (no failures in our courses!). Back in our CourseWork class, we’ll start a function that returns a grade, and write a test for it that will fail. Here’s the test.

        public class CourseWork_GetGradeMessage_Should
        {
            [Fact]
            public void ReturnTheCorrectlyFormattedMessage()
            {
                var cw = new CourseWork();
                string msg = cw.GetGradeMessage(4, 15); //these values don't matter
                string expected = "The grade is B";
                Assert.Equal(expected, msg);
            }
        }

What we’re testing is getting the expected message text. We’re not testing if GetPercent works, and we’re not testing if the GradeMark service works. When we run the test, it fails, so we write this code to try to make it pass. Some people would say that we shouldn’t bother with the GradeMark service yet, but let’s assume we’re at that point.

        public string GetGradeMessage(decimal actual, decimal maximum)
        {
            var service = new GradeMarkService();
            return "The grade is " + service.GetGrade(GetPercent(actual, maximum));
        }

We got lucky; it failed. But, remember, we can’t guarantee what letter grade will be returned. It could have passed. Run the tests enough times and it will pass.

image

Our GetGradeMessage function has a dependency on the GradeMark service, and is tightly coupled to it. We need to loosely couple that dependency by injecting it. We could do that at the method level, like this:

        public string GetGradeMessage(decimal actual, decimal maximum, GradeMarkService gradeService)
        {
            return "The grade is " + gradeService.GetGrade(GetPercent(actual, maximum));
        }

But, typically, a service like this is consumed by the class. So, we’ll inject it in the class’s constructor.

    public class CourseWork
    {
        GradeMarkService _gradeService;

        public CourseWork(GradeMarkService gradeService)
        {
            _gradeService = gradeService;
        }

        public string GetGradeMessage(decimal actual, decimal maximum)
        {
            return "The grade is " + _gradeService.GetGrade(GetPercent(actual, maximum));
        }

Great, but that doesn’t really help us, does it? We still need a GradeMarkService to pass in during our test, and control the letter grade it returns. Using some mocking frameworks, it’s possible to mock a legacy object. But in this case, we’re hoping for one of two things from our vendor to make our lives easier.

An Interface

Ideally, our vendor has programmed to an interface, using the Dependency Inversion Principle. We’ll simulate that in our fictional service class.

    public interface IGrader
    {
        string GetGrade(decimal percent);
    }

    public class GradeMarkService: IGrader
    {
        public string GetGrade(decimal percent)
        {
            var rnd = new Random();
            int code = rnd.Next(65, 70);
            return ((char)code).ToString();
        }
    }

Next, we update our class to inject the interface we’re testing, instead of the concrete instance.

public class CourseWork
{ IGrader _gradeService; public CourseWork(IGrader gradeService) { _gradeService = gradeService; }

Our class is now ready for testing. We don’t need the GradeMarkService. We just need our own mock class implementing the required interface. Back in our test project, we’ll create that.

    public class GradeMarkServiceMock: IGrader
    {
        public string GetGrade(decimal percent)
        {
            return "B";
        }
    }

And, update our tests to accept the mock object.

            [Fact]
            public void Return100PercentAs100PointZero()
            {
                var cw = new CourseWork(new GradeMarkServiceMock());
                decimal percent = cw.GetPercent(1, 1);
                Assert.Equal(100m, percent);
            }
            [Fact]
            public void RoundPercentToTwoDecimalPlaces()
            {
                var cw = new CourseWork(new GradeMarkServiceMock());
                var percent = cw.GetPercent(1, 7);
                var roundedPercent = Math.Round(percent, 2);
                Assert.Equal(roundedPercent, percent);
            }
        }

        public class CourseWork_GetGradeMessage_Should
        {
            [Fact]
            public void ReturnTheCorrectlyFormattedMessage()
            {
                var cw = new CourseWork(new GradeMarkServiceMock());
                string msg = cw.GetGradeMessage(4, 15); //these values don't matter
                string expected = "The grade is B";
                Assert.Equal(expected, msg);
            }
        }

When we run our tests a few times, the GetGradeMessage test passes consistently.

An overridable class

Our vendor could also have made the GetGrade method overridable. In that case, we’d create a mock object, override GetGrade, and always return “B”. But with a significant object, there could be many problems doing that. It’s best if we can program against interfaces, because that way  we don’t have to use the original classes at all.

What’s a real-world example? What about a shipping service that our application uses to calculate shipping rates? Several problems could exist in consuming that service instead of mocking it:

  • It could be very slow to use that service in our tests.
  • It could return inconsistent results that affect our tests.
  • We might get charged every time we use the service.

Databases are another example. Testing against a database is difficult because you want the data to always start in a consistent state. Database tests are slow. They are better left for integration tests.

Refactoring

The last step in TDD is making the code better, and also making the tests better. For example, we get an instance of the CourseWork class repeatedly. We can declare that as a class field. xUnit creates a new instance of the class for each test, so it will will always be a new instance of CourseWork.

    public class BasicTdd
    {
        public class CourseWork_GetPercent_Should
        {
            public CourseWork _cw = new CourseWork(new GradeMarkServiceMock());

            [Fact]
            public void Return100PercentAs100PointZero()
            {
                decimal percent = _cw.GetPercent(1, 1);
                Assert.Equal(100m, percent);
            }
            [Fact]
            public void RoundPercentToTwoDecimalPlaces()
            {
                var percent = _cw.GetPercent(1, 7);
                var roundedPercent = Math.Round(percent, 2);
                Assert.Equal(roundedPercent, percent);
            }
        }

        public class CourseWork_GetGradeMessage_Should
        {
            public CourseWork _cw = new CourseWork(new GradeMarkServiceMock());

            [Fact]
            public void ReturnTheCorrectlyFormattedMessage()
            {
                string msg = _cw.GetGradeMessage(4, 15); //these values don't matter
                string expected = "The grade is B";
                Assert.Equal(expected, msg);
            }
        }
    }

Of course, rerun the tests and make sure they pass!

Tag

Test-driven development isn’t natural at first. But it’s got a rat-hits-food-lever pleasure I can’t deny. Kind of like having Probe Control’s Angel Tompkins whispering in my ear.

References

30 Days of TDD

Getting Started with xUnit.net

xUnit: display only method name

xUnit: Shared Context Between Tests

7 Popular Unit Test Naming Conventions

Naming standards for unit tests

An Absolute Beginner's Tutorial on Dependency Inversion Principle