I have a function in a class that returns a value based on the state of a class property. In this example, I want HasName() to return true if Name is not null. I could simply do Returns(false), however I want it evaluate as a lambda so that it works properly if Name is modified during the test.

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());

The 2nd Console.WriteLine prints true instead of false due to scoping (referencing the 2nd mock). Resharper actually complains of "Access to modified closure". What is the correct way to do this?

有帮助吗?

解决方案

Although your design a little bit strange but you can access the generated mock object with mockThing.Object in your Setup function:

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

The problem is that you are referencing the mockThing with your lambdas and then you are reasigning it. So both setup will end up using the same instance.

Use the mocks from the dictionary and it will work:

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());
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top