Moq + Unit Testing - System.Reflection.TargetParameterCountException: несоответствие счетчика параметров
Я пытаюсь использовать лямбда с функцией с несколькими параметрами, но Moq выдает это исключение во время выполнения, когда я пытаюсь вызвать строку mock.Object.Convert(value, null, null, null);
.
System.Reflection.TargetParameterCountException: Parameter count mismatch
Код:
var mock = new Mock<IValueConverter>();
mock.Setup(conv => conv.Convert(It.IsAny<Object>(), It.IsAny<Type>(),
It.IsAny<Object>(), It.IsAny<CultureInfo>())).Returns((Int32 num) => num + 5);
var value = 5;
var expected = 10;
var actual = mock.Object.Convert(value, null, null, null);
Каков правильный способ его реализации?
Ответы
Ответ 1
Это ваше предложение Returns
. У вас есть 4 параметра, который вы настраиваете, но вы используете только 1 параметр лямбда. Я без проблем запускал следующее:
[TestMethod]
public void IValueConverter()
{
var myStub = new Mock<IValueConverter>();
myStub.Setup(conv => conv.Convert(It.IsAny<object>(), It.IsAny<Type>(), It.IsAny<object>(), It.IsAny<CultureInfo>())).
Returns((object one, Type two, object three, CultureInfo four) => (int)one + 5);
var value = 5;
var expected = 10;
var actual = myStub.Object.Convert(value, null, null, null);
Assert.AreEqual<int>(expected, (int) actual);
}
Нет исключений, тест прошел.
Ответ 2
Не ответ для OP, но, возможно, для будущих googlers:
У меня был Callback
, который не соответствовал сигнатуре устанавливаемого метода
Mock
.Setup(r => r.GetNextCustomerNumber(It.IsAny<int>()))
.Returns(AccountCounter++)
.Callback<string, int>(badStringParam, leadingDigit =>
{
// Doing stuff here, note that the 'GetNextCustomerNumber' signature is a single int
// but the callback unreasonably expects an additional string parameter.
});
Это было результатом некоторого рефакторинга, и инструмент рефакторинга, конечно, не мог понять, что подпись Callback
была неправильной
Ответ 3
Возможно, это потому, что вы проходите null
, но It.IsAny<Object>()
ожидает любой object
кроме null
? Что произойдет, если вы выполните следующее:
var actual = mock.Object.Convert(value, new object(), typeof(object), CultureInfo.CurrentCulture);
Это просто удар в темноте от меня, я больше знаком с Rhino.Mocks.
Мое второе предположение:
Посмотрев на Moq.chm, который поставляется с загрузкой,
Вы используете метод Setup(Expression<Action<T>>)
, который "Указывает настройку на посмеянный тип для вызова метода void
".
Вы хотите использовать метод te Setup<TResult>(Expression<Func<T,TResult>>)
, который "Указывает настройку на посмеянный тип для вызова метода возврата значения".
Итак, вы можете попробовать:
mock.Setup<Int32>(
conv => {
conv.Convert(
It.IsAny<Object>(),
It.IsAny<Type>(),
It.IsAny<Object>(),
It.IsAny<CultureInfo>());
return num + 5;
});
Ответ 4
В моем случае я думал, что тип в Returns<>
является типом вывода, но на самом деле это был тип ввода.
Итак, если у вас есть метод
public virtual string Foo(int a, int b) { ... }
Правильное предложение - .Returns<int, int>(...)
, NOT .Returns<string>(...)
, что и было изначально.
Моя ошибка состояла в том, что я сначала тестировал функцию с тем же исходным и возвращаемым типами - например public virtual string Foo(string a)
.