Интеграционные тесты с Topshelf для запуска C #Служба Windows

Я использую Topshelf для размещения службы Windows, написанной на C #, и теперь я хочу написать несколько интеграционных тестов. Мой код инициализации хранится в классе запуска, как показано ниже:

public class Launcher
{
    private Host host;

    /// 
    /// Configure and launch the windows service
    /// 
    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(s =>
            {
                s.ConstructUsing(() => kernel.Get());
                s.WhenStarted(w => w.Start());
                s.WhenStopped(w => w.Stop());
            });
        });

        this.host.Run(); //code blocks here
    }

    /// 
    /// Dispose the service host
    /// 
    public void Dispose()
    {
        if (this.host != null && this.host is IDisposable)
        {
            (this.host as IDisposable).Dispose();
            this.host = null;
        }
    }
}

Я хочу написать несколько интеграционных тестов, чтобы убедиться, что log4net и Ninject настроены правильно, а Topshelf запускает мой сервис. Проблема в том, что как только вы вызываете Run()на хосте Topshelf, код просто блокируется, поэтому мой тестовый код никогда не запускается.

Я думал о вызове Launch()в отдельном потоке в разделе SetUpмоих тестов, но затем мне нужно немного взломать, чтобы добавить Thread.Sleep(1000), чтобы убедиться, что тесты не запустятся до того, как Launch()завершится. законченный. Я не могу использовать правильную синхронизацию (какManualResetEvent)потому что Launch()никогда не возвращается. Текущий код:

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
    }
}

В идеале я ищу неблокирующий -способ запуска службы и программный способ ее повторной остановки, чтобы вставить мой TearDown. На данный момент мой TearDownпросто распоряжается лаунчером (, так что TearDownбуквально сносит его! ).

Есть ли у кого-нибудь опыт тестирования сервисов Topshelf таким образом? Я могу сделать вышеперечисленное относительно легко, используя стандарт ServiceHost, но я предпочитаю явную настройку и простоту установки в Topshelf.

6
задан Adam Rodger 31 July 2012 в 14:19
поделиться