Valor devuelto que se pasó a un método

391

Tengo un método en una interfaz:

string DoSomething(string whatever);

Quiero burlarme de esto con MOQ, para que devuelva lo que se haya pasado, algo como:

_mock.Setup( theObject => theObject.DoSomething( It.IsAny<string>( ) ) )
   .Returns( [the parameter that was passed] ) ;

¿Algunas ideas?

Steve Dunn
fuente

Respuestas:

527

Puede usar una lambda con un parámetro de entrada, así:

.Returns((string myval) => { return myval; });

O un poco más legible:

.Returns<string>(x => x);
mhamrah
fuente
1
Parece bastante fácil hasta que tenga que hacer esto por un método con 7 argumentos ... Cuando inspeccioné IReturnsen Moq, se define Returnspor 4 argumentos como máximo . ¿Alguna forma fácil de evitar eso? / Quiero decir, excepto modificar la fuente de Moq /
mizuki nakeshu
14
ok, está definido para hasta 9 argumentos en Moqv 4.0.0.0. resuelto :)
mizuki nakeshu
14
@mizukinakeshu Consideraría un poco refactorizador en un método de 9 argumentos, ya que parece que la clase / método está haciendo demasiado. ¿Quizás refactorice los 9 parámetros en una clase o estructura de configuración para ayudarlo más tarde?
El senador
@TheSenator De acuerdo, no recuerdo de qué se trataba, pero supongo que solo estaba hackeando algunas pruebas unitarias para el código ya existente que no debía modificar, de lo contrario, este número de argumentos definitivamente requiere una refactorización.
mizuki nakeshu
27
Solo una nota ya que esto me confundió: la cadena de .Returns<string>entrada se refiere a los parámetros de entrada y no a los valores que está devolviendo.
Jim
241

Aún más útil, si tiene múltiples parámetros, puede acceder a cualquiera / a todos ellos con:

_mock.Setup(x => x.DoSomething(It.IsAny<string>(),It.IsAny<string>(),It.IsAny<string>())
     .Returns((string a, string b, string c) => string.Concat(a,b,c));

Siempre debe hacer referencia a todos los argumentos, para que coincida con la firma del método, incluso si solo va a usar uno de ellos.

Steve
fuente
17
Esta debería ser la respuesta aceptada. Esto es exactamente lo que necesitas hacer. Cualquier otra cosa arroja una excepción de "número de argumentos esperados".
Chaim Eliyah
Sí, definitivamente es mucho más fácil de leer y funciona ReturnsAsynctambién.
Piotr Kula
1
Esta respuesta salvó el día. Nota (futuros lectores), también puedes llevarlo un poco más lejos. .Returns ((string a, string b, string c) => {string d = "wow"; return string.Concat (a, b, c, d);});
granadaCoder
1
Personalmente, esta es una respuesta mucho mejor. Tengo muy poco conocimiento de Moq pero aún así lo entendí de inmediato.
unrealsoul007
Para los métodos que devuelven void, utilicé .Callback ((string a, Exception b, string c) => throw new Exception (b.Message));
tymtam
62

El Returns<T>método genérico puede manejar esta situación muy bien.

_mock.Setup(x => x.DoSomething(It.IsAny<string>())).Returns<string>(x => x);

O si el método requiere múltiples entradas, especifíquelas así:

_mock.Setup(x => x.DoSomething(It.IsAny<string>(), It.IsAny<int>())).Returns((string x, int y) => x);
WDuffy
fuente