【问题标题】:Integration Tests With Topshelf to Start a C# Windows Service使用 Topshelf 进行集成测试以启动 C# Windows 服务
【发布时间】:2012-07-31 14:19:57
【问题描述】:

我正在使用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) 以确保测试不会在@ 之前运行987654327@ 已结束。我无法对其使用正确的同步(如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 中的显式配置和易于安装。

【问题讨论】:

    标签: c# unit-testing windows-services integration-testing topshelf


    【解决方案1】:

    https://github.com/Topshelf/Topshelf/blob/v2.3/src/Topshelf/Config/Builders/RunBuilder.cs#L113我想这就是你想要的。 AfterStartingService 可用于设置来自不同线程的ManualResetEvent

    现在这可能适合您,但这感觉过于复杂,只需部署到 dev/staging 并对您的系统进行冒烟测试即可验证。但是,如果不进一步了解您的环境,这可能是不可能的。

    【讨论】:

    • @SteveC 不再。该链接目前可以访问。
    【解决方案2】:

    我今天遇到了同样的问题,我选择将服务实例化和交互与实际的 Topshelf 托管隔离开来(在您的案例中,这仅包括使用 Ninject 解决您的服务)。

    Adam Rodger 有一个公平的观点,在快速查看 ConsoleRunHost 的 Run 方法后,它实际上会挂起等待 ManualResetEvent 并且在服务终止之前不会将控制权交还给您。

    在您的位置,为您的烟雾/回归测试编写代码,只需将内核和模块放入您的 SetUp 方法,解析服务,进行测试并将其丢弃在 TearDown

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-22
      相关资源
      最近更新 更多