Testing Windows Services with dependency injection

Last year I wrote a post on Testing Windows Services. I pointed out that recompiling and installing your Windows Service following each change is a really inefficient way to develop and test a service. Instead, I suggest that you can run and debug your service in Visual Studio simply by wrapping the service up in a test console application.

I said that I would revisit the post for services using dependency injection, so here goes. Note that the code in this article follows on directly from the code in the previous article, so you’ll need to read the previous article in order for this to make sense!

First, a quick discussion as to how you could add dependency injection to a Windows Service:

I believe the easiest way to use dependency injection in a .NET Windows Service application is to use the dependency injection engine to inject required services into the ServiceBase.Run() method in the Program class for the service:

using System.ServiceProcess;

namespace MyService
{
    public static class Program
    {
        public static void Main()
        {
            var servicesToRun = new[] { (ServiceBase)Injector.Instance.Resolve() };
            ServiceBase.Run(servicesToRun);
        }
    }
}

In order to do this, you simply need to create an empty interface for your service, which the service implements:

namespace MyService
{
    public interface IService
    {
        // No implementation
    }
}
using System.IO;
using System.ServiceProcess;

namespace MyService
{
    public partial class Service : ServiceBase, IService
    {
        public Service()
        {
            InitializeComponent();
        }

        // Service implementation...
    }
}

My original article gave an example of a service which creates and deletes a file when it starts and stops. To complete the example, let’s extract the file interaction code out as a dependency. Here’s the interface:

namespace MyService
{
    public interface IFileCreator
    {
        void Create();
        void Delete();
    }
}

…and here’s the implementation:

using System.IO;

namespace MyService
{
    public class FileCreator : IFileCreator
    {
        public void Create()
        {
            using (var stream = new FileStream("Running", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                using (var writer = new StreamWriter(stream))
                {
                    writer.WriteLine("Running");
                    writer.Flush();
                }
            }
        }

        public void Delete()
        {
            var fileInfo = new FileInfo("Running");
            if (fileInfo.Exists)
            {
                fileInfo.Delete();
            }
        }
    }
}

The injector class for the service would then look something like this:

using Castle.MicroKernel.Registration;
using Castle.Windsor;
using Castle.Windsor.Installer;

namespace MyService
{
    public static class Injector
    {
        private static readonly object InstanceLock = new object();

        private static IWindsorContainer instance;

        public static IWindsorContainer Instance
        {
            get
            {
                lock (InstanceLock)
                {
                    return instance ?? (instance = GetInjector());
                }
            }
        }

        private static IWindsorContainer GetInjector()
        {
            var container = new WindsorContainer();

            container.Install(FromAssembly.This());

            RegisterInjector(container);
            RegisterService(container);
            RegisterFileCreator(container);

            return container;
        }

        private static void RegisterInjector(WindsorContainer container)
        {
            container.Register(
                Component.For()
                .Instance(container));
        }

        private static void RegisterService(WindsorContainer container)
        {
            container.Register(
                Component.For()
                    .ImplementedBy(typeof(Service)));
        }

        private static void RegisterFileCreator(WindsorContainer container)
        {
            container.Register(
                Component.For()
                    .ImplementedBy(typeof(FileCreator)));
        }
    }
}

Note that I’ve wired up both the service (using IService) and my new FileCreator class.

The ServiceWrapper class would be exactly as in the previous example. The only change to the wrapper console application would be to change the Program, as follows:

using System;
using MyService;

namespace MyServiceWrapper
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var serviceWrapper = new ServiceWrapper();

            // Wire up service dependencies here:
            serviceWrapper.FileCreator = Injector.Instance.Resolve();

            try
            {
                serviceWrapper.TestStart();
                Console.ReadLine();
                serviceWrapper.TestStop();
            }
            catch (Exception exception)
            {
                Console.WriteLine("Error: " + exception.Message);
                Console.ReadLine();
            }
        }
    }
}

Unfortunately, in this class I’ve had to wire up all the dependencies in the ServiceWrapper manually as I haven’t found a way to do this automatically. However, this one small pain point is a significant improvement compared to compiling and installing your service each time you make a change!

Testing Windows Services

Windows Services should be part of any .NET developer’s arsenal as most enterprise solutions involve at least one Windows Service. Writing Windows Services is simple, and there are plenty of articles online to tell you how to do this. Testing Windows Services on the other hand, is a totally different story!

Of course, you could keep registering and running your service each time you make a change in order to test it, but this approach quickly becomes frustrating. A better technique that I use is to create a service wrapper console application project in the same solution as the service and run that each time I make a change. Here’s how…

Create a Windows Service. Your Solution Explorer should look a little something like this:

Testing Windows Services 1

Note that I’ve renamed Service1 to Service due to my OCD tendencies when it comes to naming conventions. I’ve created a simple test service with the following code in the Service.cs file:

using System.IO;
using System.ServiceProcess;

namespace MyService
{
    public partial class Service : ServiceBase
    {
        public Service()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            using (var stream = new FileStream("Running", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                using (var writer = new StreamWriter(stream))
                {
                    writer.WriteLine("Running");
                    writer.Flush();
                }
            }
        }

        protected override void OnStop()
        {
            var fileInfo = new FileInfo("Running");
            if (fileInfo.Exists)
            {
                fileInfo.Delete();
            }
        }
    }
}

This just creates a file in the same directory as the service when the thing starts up, and deletes the file when it stops.

The service wrapper is just a console application, so add one of these to your solution. (Please note my post on the “.NET Framework 4 Client Profile” default setting for target framework when creating console applications as this may cause issues.) You will also need to reference your service project in the console application, along with a reference to System.ServiceProcess. The wrapper should then be set as the start up project:

Testing Windows Services 2

Add a class called ServiceWrapper to the console application as follows:

namespace MyService.Wrapper
{
    public class ServiceWrapper : Service
    {
        public void TestStart()
        {
            base.OnStart(new string[] { });
        }

        public void TestStop()
        {
            base.OnStop();
        }
    }
}

Notice that the wrapper inherits from my actual service, and exposes the OnStart and OnStop methods publically. This is a simple implementation of the facade pattern, and allows the console application to call service methods.

Then add the following code to the Program class in the console application:

using System;

namespace MyService.Wrapper
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var serviceWrapper = new ServiceWrapper();

            try
            {
                serviceWrapper.TestStart();
                Console.ReadLine();
                serviceWrapper.TestStop();
            }
            catch (Exception exception)
            {
                Console.WriteLine("Error: " + exception.Message);
                Console.ReadLine();
            }
        }
    }
}

When the console application is run, the wrapper simulates the service starting up and then waits for a key press in the console window. The service will then execute as though it had been installed and ran. If you follow this example, you’ll see the file called “Running” appear and disappear. I recommend putting a breakpoint in the catch block of the Program class to help diagnose any issues you may encounter.

This approach can still be used if you use dependency injection, although you will need to manually inject any required dependencies into the service via the Program class in your wrapper. I’ll cover that in a future article.

Update: Note that if your Windows Service uses a .NET configuration file, you’ll need to share this with the console application. The best way to do this (to avoid duplicating settings between two configuration files) is to add the Windows Service configuration file to the console application as a link file. That way the console application will always use the Windows Service’s version of the file.