为单例创建虚拟实例

本文关键字:实例 虚拟 创建 单例 | 更新日期: 2023-09-27 18:36:56

我有一个单例类,我想模拟它进行测试,如下所示:

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

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

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

另一种方法是按照此方法中的建议使用FormatterServices.GetUninitializedObject()。我只需创建一个实例而不设置其任何成员。之后,我可以通过使用一些更简单的逻辑进行反思来初始化我需要的成员。无论如何,这对我来说似乎也很粗糙。

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

为单例创建虚拟实例

我建议您尝试Typemock隔离器。

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

[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>() 来创建假货,当设置您喜欢的行为时,它也将在单例的实例上设置。

希望对您有所帮助!

是的,没有真正干净的方法可以做到这一点。您要么必须更改类的接口,要么使用诸如反射/FormatterServices.GetUninitializedObject之类的技巧,就像您已经提到的那样。