Integration Tests With Topshelf to Start a C# Windows Service
===

I'm using [Topshelf][1] to host a Windows Service written in C# and I now want to write some integration tests. My initialisation code is held in a launcher class like the following:

    public class Launcher
    {
        private Host host;
    
        /// <summary>
        /// Configure and launch the windows service
        /// </summary>
        public void Launch()
        {
            //Setup log4net from config file
            log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(DEFAULT_CONFIG));

            //Setup Ninject dependency injection
            IKernel kernel = new StandardKernel(new MyModule());

            this.host = HostFactory.New(x =>
            {
                x.SetServiceName("MyService");
                x.SetDisplayName("MyService");
                x.SetDescription("MyService");

                x.RunAsLocalSystem();
                x.StartAutomatically();

                x.Service<MyWinService>(s =>
                {
                    s.ConstructUsing(() => kernel.Get<MyWinService>());
                    s.WhenStarted(w => w.Start());
                    s.WhenStopped(w => w.Stop());
                });
            });

            this.host.Run(); //code blocks here
        }
        
        /// <summary>
        /// Dispose the service host
        /// </summary>
        public void Dispose()
        {
            if (this.host != null && this.host is IDisposable)
            {
                (this.host as IDisposable).Dispose();
                this.host = null;
            }
        }
    }

I want to write some integration tests to make sure that log4net and Ninject get set up properly and Topshelf launches my service. The problem is, once you call `Run()` on the Topshelf host, the code just blocks so my test code never gets run.

I thought of calling `Launch()` in a separate thread in the `SetUp` section of my tests but then I need a bit of a hack to put in a `Thread.Sleep(1000)` to make sure the tests don't run before `Launch()` has finished. I can't use a proper sync on it (like a `ManualResetEvent`) because the `Launch()` never returns. The current code is:

    private Launcher launcher;
    private Thread launchThread;

    [TestFixtureSetUp]
    public void SetUp()
    {
        launcher = new Launcher();
        launchThread = new Thread(o => launcher.Launch());
        launchThread.Start();
        Thread.Sleep(2500); //yuck!!
    }

    [TestFixtureTearDown]
    public void TearDown()
    {
        if (launcher != null)
        {
            launcher.Dispose(); //ouch
        }
    }

Ideally what I'm looking for is a non-blocking way of launching the service and a programmatic way of stopping it again to put in my `TearDown`. At the moment my `TearDown` just disposes the launcher (so the `TearDown` literally tears it down!).

Does anyone have experience in testing Topshelf services in this way? I can do the above relatively easily using the standard `ServiceHost` but I much prefer the explicit configuration and ease of installation in Topshelf.

  [1]: http://topshelf-project.com/