6

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 がサービスを開始することを確認するために、いくつかの統合テストを作成したいと考えています。Run()問題は、 Topshelf ホストを呼び出すとコードがブロックされるため、テスト コードが実行されないことです。

Launch()テストのセクションで別のスレッドを呼び出すことを考えましたが、終了する前にテストが実行されないようにするためSetUpに少しハックする必要があります。が返されないため、( のような) 適切な同期を使用できません。現在のコードは次のとおりです。Thread.Sleep(1000)Launch()ManualResetEventLaunch()

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 でのインストールの容易さを好みます。

4

2 に答える 2

2

https://github.com/Topshelf/Topshelf/blob/v2.3/src/Topshelf/Config/Builders/RunBuilder.cs#L113あなたが望むものだと思います。別のスレッドから aAfterStartingServiceを設定するために使用できます。ManualResetEvent

これでうまくいくかもしれませんが、これは非常に複雑に感じられ、開発/ステージングにデプロイしてシステムにスモーク テストを行うだけで検証できます。ただし、環境をよく理解していなければ、それは不可能かもしれません。

于 2012-08-01T12:25:35.653 に答える
0

今日も同じ問題があり、サービスのインスタンス化と相互作用を実際の Topshelf ホスティングから分離することにしました (これは、Ninject を使用してサービスを解決することだけで構成されています)。

Adam Rodger の指摘は的を射ており、 の Run メソッドをざっと見てみると、ConsoleRunHost実際には を待機するためにハングしManualResetEvent、サービスが終了するまで制御が返されません。

あなたの場所で、スモーク/回帰テストをコーディングするには、カーネルとモジュールをSetUpメソッドに取り込み、サービスを解決し、テストを実行して、TearDown

于 2017-01-11T00:27:43.460 に答える