c# - 如何在我的单元测试中隔离单例?

标签 c# unit-testing rhino-mocks nunit-2.5

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

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

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

最佳答案

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

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

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

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

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

我见过但个人不太喜欢的替代方法是在单例中引入一个 setter ,这样您就可以用单元测试所需的模拟对象“交换”具体类。此 setter 将仅用于单元测试,并且可以标记为内部,因此程序集之外的类无法访问。然后您可以使用 InternalsVisibleTo属性为您的单元测试程序集创建一个特殊的异常(exception),以便它可以看到和使用 setter 。

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

关于c# - 如何在我的单元测试中隔离单例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7223059/

相关文章:

java - 使用 Spring Boot @WebMvcTest 进行测试时如何从我的上下文中排除其他 @Controller

c# - 为什么每个 [TestMethod] 都会多次调用 [TestClass] 的构造函数?

c# - 连接到单元测试中的事件

mocking - 生成的服务模拟 : everything but RhinoMocks fails?

.net - Rhino Mocks 中所有输入的 stub 返回值

c# - DateTimeOffset?.ToString(字符串格式)

c# - 如何检查 Linq 查询结果中的 DBNull 值

c# - 通过标签在 C# 中拆分文本

c# - 在 using 语句中创建的 Rhino 模拟和对象

c# - 提高 ASP.NET 应用程序的性能