Moq不匹配(简单)设置

时间:2011-11-24 08:09:59

标签: c#-4.0 moq

我是Moq的新手,并且看起来似乎是个愚蠢的问题。 如果我根据循环执行设置它将无法匹配,但如果我手动进行“ide​​nticatal”设置,我会得到一个匹配。

我正在使用NuGet的Moq 4.0.10827

我的界面被嘲笑很简单:

public interface IMyInterface
{
    string GetValue(string input);
}

整个测试程序如下。 两种方法的预期输出相同,但版本2()

不打印“Foo”

代码:

class Program
{
    static void Main(string[] args)
    {
        Version1();
        Console.WriteLine("---------");
        Version2();
        Console.WriteLine("---------");
        Console.ReadKey();
    }

    private static void Version1()
    {
        var mock = new Mock<IMyInterface>();

        mock.Setup(x => x.GetValue(It.Is<string>(s => s == "Foo"))).Returns("Foo");
        mock.Setup(x => x.GetValue(It.Is<string>(s => s == "Bar"))).Returns("Bar");

        IMyInterface obj = mock.Object;

        Console.WriteLine(obj.GetValue("Foo"));
        Console.WriteLine(obj.GetValue("Bar"));
    }

    private static void Version2()
    {
        var mock = new Mock<IMyInterface>();

        string[] keys = new string[] { "Foo", "Bar" };

        foreach (string key in keys)
        {
            mock.Setup(x => x.GetValue(It.Is<string>(s => s == key))).Returns(key);
        }

        IMyInterface obj = mock.Object;

        Console.WriteLine(obj.GetValue("Foo")); // Does not match anything
        Console.WriteLine(obj.GetValue("Bar"));            
    }
}

我认为我错过了什么......但是什么?

节目输出:

Foo
Bar
---------

Bar
---------

编辑:程序输出

2 个答案:

答案 0 :(得分:2)

这是一种更通用的方式,单独使用此设置可以让您返回从参数中获得的内容。

mock.Setup(item => item.GetValue(It.IsAny<string>())).Returns((string input) => input);

通过使用It.Is<string>(s => s == "Bar"),您可能会覆盖第一个谓词。尝试更改顺序或字符串,并检查它的行为方式。

如果你想分别检查价值,你可以做这样的事情

mock.Setup(item => item.GetValue("Foo")).Returns("Foo");
mock.Setup(item => item.GetValue("Bar")).Returns("Bar");

循环:

foreach (string key in keys)
{
    mock.Setup(x => x.GetValue(key)).Returns(key);
}

答案 1 :(得分:0)

@Ufuk是对的。澄清一下,这与Moq无关。这是经典的“访问修改后的闭包”问题(这是ReSharper给出的警告信息)。

例如:

void Main()
{
    var actions = new List<Func<string, bool>>();

    string[] keys = new string[] { "Foo", "Bar" };

    foreach (string key in keys)
    {
        actions.Add(s => s == key);
    }

    foreach (var action in actions)
    {
        Console.WriteLine("Is Foo: " + action("Foo"));
        Console.WriteLine("Is Bar: " + action("Bar"));
        Console.WriteLine();
    }
}

结果:

Is Foo: False
Is Bar: True

Is Foo: False
Is Bar: True

请参阅Jon Skeet's answer to C# Captured Variable In Loop和Eric Lippert的Closing over the loop variable considered harmful