为单例创建虚拟实例

Create Dummy-instance for singleton

我有一个单例-class,我想模拟它以进行如下测试:

public class MyClass {
    private readonly static MyClass _instance = new MyClass();
    public MyClass Instance { get { return this._instance; }}

    private MyClass() 
    {
        DoSomething();
    }
}

由于 MyClass 的私有构造函数有一些繁重的逻辑,包括读取一些配置文件,我想模拟单例实例以进行测试。但是我看不出有什么办法可以做到这一点,因为我无法标记 属性 Instance 虚拟。

我想我有两个机会,但我不知道哪个更合适。第一个是使(私有的)DomeSomething 方法可覆盖(意思是 protectedvirtual)并在派生的 class 中为它创建一些虚拟实现(模拟).然而,为了测试而修改我的 class 结构对我来说似乎并不合适。

另一种方法是使用 FormatterServices.GetUninitializedObject(),如 this approach 中所建议的那样。我只是创建一个实例,而不设置其成员的 any。之后我可以使用一些更简单的逻辑通过反射来初始化我需要的成员。无论如何,这对我来说也很粗糙。

我还有其他机会吗?还是我必须在这两个烦人的之间做出选择?

是的,没有真正干净的方法来做到这一点。您要么必须更改 class 的界面,要么像您已经提到的那样使用 reflection/FormatterServices.GetUninitializedObject 这样的技巧。

我建议您尝试 Typemock Isolator

其模拟单例的解决方案非常简单,无需更改生产代码(您的私有方法仍然是私有的)。看看这个例子:

[TestMethod]
public void TestMethod1()
{
    var fakeSingleton = Isolate.Fake.AllInstances<MyClass>();

    Isolate.WhenCalled(() => fakeSingleton.someFunction()).WillReturn(true);

    Assert.IsTrue(MyClass.Instance.someFunction());
 }

您正在通过调用 Isolate.Fake.AllInstances<MyClass>() 创建一个伪造的,当设置您喜欢的行为时,它也会在单例实例上设置。

希望对您有所帮助!