为单身

时间:2016-03-01 12:15:30

标签: c# reflection mocking singleton

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

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

    private MyClass() 
    {
        DoSomething();
    }
}

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

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

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

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

2 个答案:

答案 0 :(得分:1)

我建议你试试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>()创建假名,并且它也将在单例的实例上设置。

希望它有所帮助!

答案 1 :(得分:0)

是的,没有真正干净的方法来做到这一点。您可能需要更改类的接口或使用像您已经提到的那样的反射/ FormatterServices.GetUninitializedObject等技巧。