Я использую Topshelf для размещения службы Windows, написанной на C #, и теперь я хочу написать несколько интеграционных тестов. Мой код инициализации хранится в классе запуска, как показано ниже:
public class Launcher
{
private Host host;
///
/// Configure and launch the windows service
///
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(s =>
{
s.ConstructUsing(() => kernel.Get());
s.WhenStarted(w => w.Start());
s.WhenStopped(w => w.Stop());
});
});
this.host.Run(); //code blocks here
}
///
/// Dispose the service host
///
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()
завершится. законченный. Я не могу использовать правильную синхронизацию (как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.