2011-10-10 9 views
61

Estoy tratando de usar una lambda con una función de múltiples parámetros, pero Moq arroja esta excepción en el tiempo de ejecución cuando intento llamar a la línea mock.Object.Convert(value, null, null, null);.Moq + Prueba de la unidad - System.Reflection.TargetParameterCountException: desajuste del conteo de parámetros

System.Reflection.TargetParameterCountException: Parameter count mismatch

El código es:

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); 

¿Cuál es la forma correcta de ponerlo en práctica?

Respuesta

108

Es su cláusula Returns. Tienes un método de 4 parámetros que estás configurando, pero solo estás usando un parámetro lambda 1. Ejecuté lo siguiente sin problema:

[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); 
} 

Sin excepciones, se aprobó la prueba.

+0

Iba a preguntar si esto era una prueba del marco o no, pero pensé que daría el beneficio de la duda de que tal vez era un código provisional para intentar que el simulacro se comportara correctamente. –

+0

Supongo que también, pero me hizo reír de todos modos. –

+0

Te escucho. Cuando ejecuté el código, pensé "sí, las bibliotecas de framework todavía funcionan". :) –

2

Tal vez sea porque está de paso null pero It.IsAny<Object>() está esperando cualquier object excepto null? ¿Qué pasa si lo hace lo siguiente ?:

var actual = mock.Object.Convert(value, new object(), typeof(object), CultureInfo.CurrentCulture); 

Esto es sólo una puñalada en la oscuridad de mi parte, estoy más familiarizado con Rhino.Mocks.


Mi segunda conjetura:

Después de examinar el Moq.chm que viene con la descarga,

Está utilizando el método Setup(Expression<Action<T>>) la que "Especifica una configuración del tipo de burlas por una llamada a un método void ".

Quiere el método Setup<TResult>(Expression<Func<T,TResult>>) que "Especifica una configuración en el tipo de imitación para una llamada a un método de devolución de valor".

lo que podría intentar:

mock.Setup<Int32>(
    conv => { 
     conv.Convert(
      It.IsAny<Object>(), 
      It.IsAny<Type>(), 
      It.IsAny<Object>(), 
      It.IsAny<CultureInfo>()); 
     return num + 5; 
     }); 
+0

mock.Setup infiere el tipo de devolución como Objeto porque el método Convert devuelve un Objeto. –

4

No es una respuesta de OP pero tal vez para futuros empleados de Google:

que tenía un Callback que no coincide con la firma del método es la configuración

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. 
    }); 

Este fue el resultado de algún refactorización y la herramienta de refactorización por supuesto no pudo darse cuenta de que la firma Callback era incorrecta

+0

wow, me estaba golpeando la cabeza contra este mismo problema y sigo pasando por alto la devolución de llamada hasta que leo su publicación. Muy útil y me alegra que lo hayas publicado. – dblood

1

En mi caso, pensé que el tipo en Returns<> es el tipo de salida, pero en realidad era el tipo de entrada (s).

Así que si usted tiene un método

public virtual string Foo(int a, int b) { ... } 

La cláusula correcta es .Returns<int, int>(...), NO .Returns<string>(...) que es lo que se pensaba inicialmente.

Mi error fue porque estaba probando una función con el mismo tipo de entrada y devolución inicialmente, por ejemplo public virtual string Foo(string a).