Moq не соответствует (простая) настройка - PullRequest
2 голосов
/ 24 ноября 2011

Я новичок в Moq, и у меня возникла глупая проблема.Если я выполняю настройку на основе цикла, она не будет соответствовать, но если я выполню «одинаковую» настройку вручную, я получу совпадение.

Я использую Moq 4.0.10827 от NuGet

Мой интерфейс очень прост:

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

Вся программа тестирования приведена ниже.Ожидаемый вывод одинаков для обоих методов, но «Foo» не печатается для Version2 ()

Код:

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 ]

2 голосов
/ 24 ноября 2011

Вот более общий способ, одна только эта настройка позволит вам вернуть то, что вы получаете от параметра.

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);
}
0 голосов
/ 24 ноября 2011

@ Уфук правильно.Чтобы уточнить, это не имеет ничего общего с 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

См. Ответ Джона Скита на C # Captured Variable In Loop и ответ Эрика Липперта Закрытие переменной цикла, считающейся вредной .

...