簡體   English   中英

與Topshelf集成測試以啟動C#Windows服務

[英]Integration Tests With Topshelf to Start a C# Windows Service

我正在使用Topshelf托管用C#編寫的Windows服務,現在我想編寫一些集成測試。 我的初始化代碼保存在啟動器類中,如下所示:

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

我想編寫一些集成測試,以確保正確設置log4net和Ninject並由Topshelf啟動我的服務。 問題是,一旦您在Topshelf主機上調用Run() ,代碼便會阻塞,因此我的測試代碼將永遠不會運行。

我想呼吁的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確實將其TearDown了!)。

有沒有人有過以這種方式測試Topshelf服務的經驗? 我可以使用標准ServiceHost相對輕松地完成上述操作,但是我更喜歡在Topshelf中進行顯式配置和易於安裝。

https://github.com/Topshelf/Topshelf/blob/v2.3/src/Topshelf/Config/Builders/RunBuilder.cs#L113我想這就是您想要的。 AfterStartingService可用於從其他線程設置ManualResetEvent

現在,這可能對您來說可行,但是這感覺太過復雜了,僅通過部署到開發/登台並對系統進行煙霧測試即可​​得到驗證。 但是,如果不進一步了解您的環境,那將是不可能的。

今天,我遇到了同樣的問題,我選擇將服務實例化和交互與實際的Topshelf托管隔離開(這只不過是在您的情況下使用Ninject解決服務)。

亞當·羅傑(Adam Rodger)有一個公平的觀點,在快速瀏覽了ConsoleRunHost的Run方法ConsoleRunHost ,它實際上將掛起以等待ManualResetEvent並且直到該服務終止之前都不會將控件退還給您。

在您的地方,要對冒煙/回歸測試進行編碼,只需將內核和模塊放入您的SetUp方法中,解析服務,進行測試並將其放置在TearDown

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM