如何使用Microsoft Fakes Shim隔离(绕道)类的构造函数?

时间:2012-07-24 13:54:09

标签: c# unit-testing microsoft-fakes

是否有可能使用Microsoft Fakes隔离/替换类的构造函数?

在Mole(Fakes的前身)中找到了一个例子:http://thecurlybrace.blogspot.co.at/2011/11/how-do-i-detour-mole-type-constructor.html

我试过像这样的结构

ShimStreamReader.Constructor = @this => ShimStreamReader.ConstructorString(@this, "Test");

但它说缺少get访问器。为了澄清它可以更换像

这样的东西
new StreamReader("filename")

使用像这样的静态输入

new StreamReader(new MemoryStream(Encoding.Default.GetBytes("33\r\n1\r\n16\r\n5\r\n7")))

这样我就不必模拟Read,ReadLine等。

2 个答案:

答案 0 :(得分:4)

using (ShimsContext.Create())
{
    ShimStreamReader.ConstructorString = 
        delegate(StreamReader @this, string @string)
        {
            var shim = new ShimStreamReader(@this);
            shim.Read = () => 42;
        };

    var target = new StreamReader("MeaningOfLife.txt");
    Assert.AreEqual(42, target.Read());
}

答案 1 :(得分:4)

可以通过反射替换和调用不同的构造函数:

“因此,当您替换构造函数时,您应该在构造函数中进行所有初始化。对于StreamReader构造函数可能是不可能的,因为您不知道对象是如何由原始构造函数内部初始化的,并且您没有访问对象的私有成员。

因此,我们可以使用反射来调用原始构造函数来初始化对象然后使用它。“ - 请参阅Vikram Agrawals在http://social.msdn.microsoft.com上的答案

所以关于我的问题的代码看起来像这样:

ShimStreamReader.ConstructorString = (@this, value) =>
{
    ConstructorInfo constructor = typeof (StreamReader).GetConstructor(new[] {typeof (Stream)});
    constructor.Invoke(@this, new object[] {new MemoryStream(Encoding.Default.GetBytes("33\r\n1\r\n16\r\n5\r\n7"))});
};