Функция вызывается, когда я не ожидаю этого с NSubstitute - PullRequest
3 голосов
/ 02 августа 2011

Я получаю поведение, которого я не ожидал от NSubstitute при настройке моих макетов для вызова функции. Упрощенная версия поведения

[Test]
public void NSubstituteTest()
{
    var mockedFoo = Substitute.For<IFoo>();

    mockedFoo.GenerateString(Arg.Any<string>()).Returns(x => GetValue(x.Args()[0]));
    mockedFoo.GenerateString("0").Returns("hi");


    string result1 = mockedFoo.GenerateString("0");
    string result2 = mockedFoo.GenerateString("1");

    Assert.AreEqual("hi", result1);
    Assert.AreEqual("1", result2);
}

private string GetValue(object val)
{
    string returnValue = val != null ? val.ToString() : "I am null";
    System.Diagnostics.Trace.WriteLine(returnValue);
    return returnValue;
}

Тест пройден, но я получаю вывод: 0 1

Это указывает на то, что вызов mockedFoo.GenerateString ("0"); фактически приводит к вызову функции GetValue ().

Если я сделаю то же самое с Moq:

[Test]
public void MoqTest()
{
    var mockedFoo = new Mock<IFoo>();

    mockedFoo.Setup(x => x.GenerateString(It.IsAny<string>())).Returns((object s) => GetValue(s));
    mockedFoo.Setup(x => x.GenerateString("0")).Returns("hi");


    string result1 = mockedFoo.Object.GenerateString("0");
    string result2 = mockedFoo.Object.GenerateString("1");

    Assert.AreEqual("hi", result1);
    Assert.AreEqual("1", result2);
}

Тогда мои тесты также проходят, но я получаю результат: 1

Указывает, что функция не была вызвана.

Это поведение где-то описано, или я что-то настраиваю неправильно?

1 Ответ

5 голосов
/ 02 августа 2011

Это побочный эффект от того, как работает NSubstitute: чтобы получить конкретный синтаксис, ему нужно вызвать метод, чтобы получить ссылку на этот метод.

Moq и другие используют лямбды и могут выбирать конкретныйметод оттуда, без необходимости запускать сам метод.(Это означает, что NSubstitute также не может обнаружить или сгенерировать вызовы не виртуальных методов.)

В следующем выпуске будет обходной путь для некоторых случаев, когда это вызывает проблемы (хотя и не идеальный: выВ вызове нужно будет использовать сопоставление аргументов, которое устанавливает возврат, чтобы NSub заранее знал, что это не настоящий вызов), но фундаментальная проблема перехвата реальных вызовов методов останется.

...