【发布时间】: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