Moq lambda的参考成员

时间:2014-03-27 20:18:09

标签: moq

我在类中有一个函数,它根据类属性的状态返回一个值。在这个例子中,如果Name不为null,我希望HasName()返回true。我可以简单地做Returns(false),但我希望它作为lambda进行评估,以便在测试期间修改Name时它可以正常工作。

public interface IThing
{
    string Name { get; set; }
    bool HasName();
}

var mocks = new Dictionary<string, IThing>();
Mock<IThing> mockThing;

mockThing = new Mock<IThing>();
mockThing.SetupProperty(m => m.Name, "test");
mockThing.Setup(m => m.HasName()).Returns(() =>
    {
        return mockThing.Object.Name != null;
    });
mocks["first"] = mockThing.Object;

mockThing = new Mock<IThing>();
mockThing.SetupProperty(m => m.Name, "test");
mockThing.Setup(m => m.HasName()).Returns(() =>
    {
        return mockThing.Object.Name != null;
    });
mocks["second"] = mockThing.Object;


Console.WriteLine(mocks["first"].HasName());
mocks["first"].Name = null;
Console.WriteLine(mocks["first"].HasName());

由于作用域(引用第二个模拟),第二个Console.WriteLine打印true而不是false。 Resharper实际上抱怨&#34;访问修改后的封闭&#34;。这样做的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

虽然您的设计有点奇怪,但您可以在mockThing.Object函数中使用Setup访问生成的模拟对象:

mockThing.Setup(m => m.HasName()).Returns(() =>
{
     return mockThing.Object.Name != null;
});

var thing = mockThing.Object;
var hasName = thing.HasName(); // true because Name returns "test"
thing.Name = null;
hasName = thing.HasName(); // false

问题是你正在用你的lambdas引用mockThing然后你正在重新分配它。因此,两个设置最终都将使用相同的实例。

使用字典中的模拟,它将起作用:

var mocks = new Dictionary<string, IThing>();
Mock<IThing> mockThing;

mockThing = new Mock<IThing>();
mocks["first"] = mockThing.Object;
mockThing.SetupProperty(m => m.Name, "test");
mockThing.Setup(m => m.HasName()).Returns(() =>
{
    return mocks["first"].Name != null;
});


mockThing = new Mock<IThing>();
mocks["second"] = mockThing.Object;
mockThing.SetupProperty(m => m.Name, "test");
mockThing.Setup(m => m.HasName()).Returns(() =>
{
    return mocks["second"].Name != null;
});


Console.WriteLine(mocks["first"].HasName());
mocks["first"].Name = null;
Console.WriteLine(mocks["first"].HasName());