J'utilise Topshelf pour héberger un service Windows écrit en C# et je veux maintenant écrire des tests d'intégration. Mon code d'initialisation est maintenu dans une classe de lanceur comme ce qui suit:Tests d'intégration avec Topshelf pour démarrer un service Windows C#
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;
}
}
}
Je veux écrire des tests d'intégration pour vous assurer que log4net et Ninject se mettre en place correctement et Topshelf lance mon service. Le problème est, une fois que vous appelez Run()
sur l'hôte Topshelf, le code bloque juste de sorte que mon code de test ne soit jamais exécuté.
Je pensais que d'appeler Launch()
dans un thread séparé dans la section SetUp
de mes tests, mais je besoin d'un peu un hack pour mettre dans un Thread.Sleep(1000)
pour vous assurer que les tests ne fonctionnent pas avant Launch()
a terminé. Je ne peux pas utiliser une synchronisation correcte dessus (comme un ManualResetEvent
) parce que le Launch()
ne revient jamais. Le code actuel est:
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
}
}
Idéalement ce que je suis à la recherche est un moyen non-blocage du lancement du service et d'une manière programmatique de l'arrêter à nouveau pour mettre dans mon TearDown
. En ce moment, mon TearDown
ne dispose que du lanceur (donc le TearDown
le déchire littéralement!).
Est-ce que quelqu'un a de l'expérience dans le test des services Topshelf de cette façon? Je peux faire ce qui précède relativement facilement en utilisant la norme ServiceHost
mais je préfère de loin la configuration explicite et la facilité d'installation dans Topshelf.
Le lien est rompu – SteveC
@ SteveC plus maintenant. Le lien est accessible pour le moment. – dotnetguy