5

我正在使用Topshelf來託管以C#編寫的Windows服務,現在我想編寫一些集成測試。我的初始化代碼在發射類像下面的召開方式:使用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(),代碼就會阻塞,所以我的測試代碼永遠不會運行。

我想在我的測試中SetUp部分調用Launch()在一個單獨的線程,但後來我需要一個黑客位的放在一個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中的顯式配置和易於安裝。

回答

2

https://github.com/Topshelf/Topshelf/blob/v2.3/src/Topshelf/Config/Builders/RunBuilder.cs#L113我想是你想要的。 AfterStartingService可用於設置不同線程的ManualResetEvent

現在這可能會適合您,但這種感覺過於複雜,可以通過部署到dev/staging並對您的系統執行冒煙測試來驗證。但是,如果不瞭解您的環境,那可能是不可能的。

+3

鏈接已損壞 – SteveC 2015-05-03 15:04:52

+0

@ SteveC不在了。該鏈接目前可以訪問。 – dotnetguy 2016-05-05 04:52:36

0

今天我有同樣的問題,我選擇從實際的Topshelf託管(它只不過是在您的案例中使用Ninject解決您的服務而構成)來隔離服務實例和交互。

Adam Rodger有一個公平點,在快速查看ConsoleRunHost的Run方法後,它實際上會掛起以等待ManualResetEvent,並且在服務終止之前不會給您控制權。

在你的地方,編寫你的煙/迴歸測試,只得到內核和模塊到您的SetUp方法,解決了服務,做您的測試和部署其在TearDown

相關問題