关于c#:如何对Windows服务进行单元测试?

关于c#:如何对Windows服务进行单元测试?

How can I unit test a Windows Service?

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

我是TDD(测试驱动开发)的新手。

首先,甚至可以对Windows Service进行单元测试吗?

Windows服务类是从ServiceBase派生的,ServiceBase具有可重写的方法,

  • OnStart
  • 停止
  • 我如何触发这些方法被调用,就好像单元测试是按正确顺序调用这些方法的实际服务一样?

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

    我已经看过WCF服务问题,但是对我来说这没有任何意义,因为我从未处理过WCF服务。


    我可能会建议设计您的应用程序,以便Windows Service中的" OnStart"和" OnStop"替代仅调用类库程序集上的方法。这样,您可以针对类库方法自动执行单元测试,并且设计还从Windows Service的实现中抽象出您的业务逻辑。

    在这种情况下,在Windows Service上下文中测试" OnStart"和" OnStop"方法本身将是一个集成测试,而不是自动化的测试。


    我通过不直接测试服务,而是测试服务的功能来对Windows服务进行单元测试。

    通常,我为该服务创建一个程序集,并为该服务创建另一个程序集。然后,我针对第二个程序集编写单元测试。

    这种方法的好处是您的服务非常薄。基本上,它所做的只是调用方法在正确的时间进行正确的工作。您的另一个程序集包含您的服务打算完成的所有工作。这使得测试非常容易,并且可以根据需要轻松重用或修改。


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

    一个示例开始是

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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
      {
        // ...
      }
    }

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


    我会使用Windows服务类(在启动/停止服务时运行的服务类),就像真实系统的代理一样。我看不出您的服务背后的代码与任何其他编程应该有什么不同。 onStart和onStop方法只是触发事件,例如按GUI上的按钮。

    因此,您的Windows服务类是非常薄的类,可与Windows窗体相比。它调用您的业务逻辑/域逻辑,然后执行应做的事情。您所要做的就是确保您在onStart和onStop中调用的方法按预期工作。至少那是我会做的;-)


    设计测试是一个不错的策略,因为许多答案都建议通过委托域对象使OnStartOnStop方法保持精简。

    但是,如果由于某些原因测试确实需要执行服务方法,则可以使用如下代码从测试方法中调用它们(在此示例中调用OnStart):

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

    自动关闭,关闭条件下的测试窗口服务
    网络断开连接时测试窗口服务
    测试窗口服务选项自动启动,手动等


    盖伊可能是最好的答案。

    无论如何,如果确实需要,您可以按照MSDN文档中的说明在单元测试中调用这两种方法,但是由于它们是受保护的,因此需要使用Reflection。


    推荐阅读