Подтвердить что ты не робот

Как использовать метод Moq, который имеет необязательный аргумент в своей сигнатуре без явного указания его или использования перегрузки?

Учитывая следующий интерфейс:

public interface IFoo
{
    bool Foo(string a, bool b = false);
}

Попытка издеваться над ним с помощью Moq:

var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>())).Returns(false);

дает следующую ошибку во время компиляции:

Дерево выражений может не содержать вызов или вызов, который использует необязательные аргументы

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

Мой вопрос: что я должен делать, учитывая, что вышеизложенное не будет исправлено в ближайшее время? Являются ли мои варианты только для того, чтобы либо явным образом устанавливать значение по умолчанию для необязательного параметра каждый раз, когда я его издеваюсь (какой вид побеждает точка указания в первую очередь), или для создания перегрузки без bool (например, что бы я сделал до С# 4)?

Или кто-нибудь может найти более умный способ преодолеть эту проблему?

4b9b3361

Ответ 1

Я считаю, что ваш единственный выбор прямо сейчас заключается в явном включении параметра bool в настройку для Foo.

Я не думаю, что это побеждает цель указания значения по умолчанию. Значение по умолчанию - это удобство для вызова кода, но я думаю, что вы должны быть явным в своих тестах. Скажем, вы можете не указывать параметр bool. Что произойдет, если в будущем кто-то изменит значение по умолчанию b на true? Это приведет к неудачным испытаниям (и по праву), но их будет сложнее исправить из-за скрытого предположения, что b false. Явное указание параметра bool имеет еще одно преимущество: оно улучшает читаемость ваших тестов. Кто-то, проходящий через них, быстро узнает, что есть одна функция Foo, которая принимает два параметра. Что мои 2 цента, по крайней мере:)

Как для указания его каждый раз, когда вы издеваетесь над этим, не дублируйте код: создайте и/или инициализируйте макет в функции, чтобы у вас была только одна точка изменения. Если вы действительно этого захотите, вы можете преодолеть кажущееся короткое замыкание Moq путем дублирования параметров Foo в этой функции инициализации:

public void InitFooFuncOnFooMock(Mock<IFoo> fooMock, string a, bool b = false)
{
    if(!b)
    {
        fooMock.Setup(mock => mock.Foo(a, b)).Returns(false);
    }
    else
    {
        ...
    }
}

Ответ 2

Только что столкнулся с этой проблемой сегодня, Moq не поддерживает этот прецедент. Итак, кажется, что для этого случая будет достаточно переопределения метода.

public interface IFoo
{
    bool Foo(string a);

    bool Foo(string a, bool b);
}

Теперь доступны оба метода, и этот пример будет работать:

var mock = new Mock<IFoo>();
mock.Setup(mock => mock.Foo(It.IsAny<string>())).Returns(false);