我的程序中有一个静态类。在静态构造函数中,我创建了服务实例。服务的代理是单例。
我必须为这个类编写单元测试,当然我想隔离这个服务。 我该怎么做?
在我的项目中,我们使用 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/