1

我的程序中有一个静态类。在静态构造函数中,我创建了服务实例。服务的代理是一个单例。

我必须为这个类编写单元测试,当然我想隔离这个服务。我该怎么做?

在我的项目中,我们使用 Rhino.Mocks。

4

2 回答 2

3

从单元测试的角度来看,单例是有问题的。我假设使用您的 Singleton 的类正在通过静态属性检索实例:

class MyClass()
{
   public MyClass()
   {
      var myService = StaticFoo.MyServiceInstance;
   }
}

这相当于在本地创建一个具体的类实例,因为“如何到达”您的 Singleton 的知识是您的类实现的一部分。您需要做的是删除该知识并注入此依赖项,就像您在非单例上注入其他依赖项一样。最直接的方法是构造函数注入:

class MyClass()
{
   public MyClass(IService myService)
   {
     //..
   }
}

另一个需要的部分是确保您的服务中的所有接口方法/属性都定义为虚拟或定义您的服务实现的接口或抽象基类,并定义您的类MyClass在此服务上使用的所有操作。这是必需的,因为大多数单元测试框架(包括 Rhino-Mocks)只能模拟虚拟方法/属性。

我见过但个人不太喜欢的另一种方法是在 Singleton 中引入 setter,以便您可以用单元测试所需的模拟对象“交换”具体类。此设置器仅用于单元测试,并且可以标记为内部,因此您的程序集之外的类无权访问。然后,您可以使用该InternalsVisibleTo属性为您的单元测试程序集创建一个特殊例外,以便它可以查看和使用 setter。

这种方法的主要优点是它需要更少的重构来获得可测试的解决方案,但代价是“污染”静态 Singleton 持有者的接口。由于在大多数情况下,首先不需要单例,因此我会考虑首先重构为构造函数注入。

于 2011-08-28T18:51:35.883 回答
1

您需要在您的类上有一个接受服务实例的公共初始化方法。然后,您可以使用初始化方法注入模拟对象。

于 2011-08-28T18:46:04.520 回答