如何对Windows服务进行单元测试?

64

.NET Framework: 2.0 首选语言:C#

我对TDD(测试驱动开发)还很陌生。

首先,Windows服务可以进行单元测试吗?

Windows服务类派生自ServiceBase,该类有可重写方法:

  1. OnStart
  2. OnStop

我应该如何触发这些方法被调用,就像单元测试是一个真正的服务一样按照正确顺序调用这些方法?

此时,我是否在进行单元测试?还是集成测试?

我看了WCF服务问题,但它没有任何意义,因为我从未处理过WCF服务。

7个回答

90

我建议你设计你的应用程序,使得Windows服务中的"OnStart"和"OnStop"方法只是调用类库程序集中的方法。这样你就可以自动化单元测试来测试类库方法,并且这种设计还将你的业务逻辑与Windows服务的实现分离。

在这种情况下,在Windows服务上下文中测试"OnStart"和"OnStop"方法本身将成为一项集成测试,而不是你要自动化的内容。


35

我进行单元测试的方式是不直接测试服务,而是测试服务所做的事情。

通常我为服务创建一个程序集,另一个程序集用于定义服务需要完成的任务。然后,我编写针对第二个程序集的单元测试。

这种方法的好处在于你的服务非常轻量级。它基本上只是在正确的时间调用方法来完成正确的工作。你的另一个程序集包含所有你的服务意图要完成的具体工作。这使得测试非常容易,同时也方便重用或根据需要进行修改。


不错的方法,这也将您的业务逻辑与服务分离。 - JPReddy

10

我会从这里开始。它展示了如何在C#中启动和停止服务。

一个启动的示例:

public static void StartService(string serviceName, int timeoutMilliseconds)
{
  ServiceController service = new ServiceController(serviceName);
  try
  {
    TimeSpan timeout = TimeSpan.FromMilliseconds(timeoutMilliseconds);

    service.Start();
    service.WaitForStatus(ServiceControllerStatus.Running, timeout);
  }
  catch
  {
    // ...
  }
}

我也主要通过控制台应用程序测试服务,模拟服务的操作。这样我的单元测试就完全自动化了。


1
这段代码返回什么service.WaitForStatus? WaitForStatus()函数有什么用途?请解释一下。谢谢。 - Mou

6
我会使用Windows服务类(当您启动/停止服务时运行的类)作为真实系统的代理。我认为,您的服务背后的代码与任何其他编程代码没有什么不同。 onStart和onStop方法只是触发的事件,就像在GUI上按下按钮一样。
因此,您的Windows服务类非常简单,可与Windows窗体相媲美。它调用您的业务逻辑/领域逻辑,然后执行其应该执行的操作。您需要做的就是确保您在onStart和onStop中调用的方法能够正常工作。这至少是我会这样做的;-)

3

设计测试是一个好策略,正如许多答案指出的那样,建议您通过委托给域对象使OnStartOnStop方法保持非常简洁。

然而,如果您的测试出于某种原因确实需要执行服务方法,您可以使用以下代码从测试方法中调用它们(在此示例中调用OnStart):

serviceInstance.GetType().InvokeMember("OnStart", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, serviceInstance, new object[] {new string[] {}});

0

测试在自动关机、关闭条件下的Windows服务 测试在网络断开、连接时的Windows服务 测试Windows服务选项,如自动启动、手动等


1
我认为他并不是在询问关于测试Windows服务的类型。 - JPReddy

-1

这个人的回答可能是最好的。

无论如何,如果你真的想要,你可以像MSDN文档中描述的那样在单元测试中调用这两个方法,但是由于它们是受保护的,你需要使用反射。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接