繁体   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