2010-05-14 11 views

Respuesta

60

difícil de superar https://github.com/Moq/moq4/wiki/Quickstart

Si eso no es lo suficientemente claro, yo lo llamaría un error doc ...

EDIT: En respuesta a su aclaración ...

Para cada burlado Setup método de llevar a cabo, se llega a indicar cosas como:

  • restricciones en los insumos
  • el valor de/forma en la que el valor de retorno (si lo hay) es que se deriva

El mecanismo .Callback dice: "No puedo describirlo en este momento, pero cuando una forma llamada esto sucede, llámame y haré lo que sea necesario ". Como parte de la misma cadena de llamadas fluidas, puede controlar el resultado para devolver (si corresponde) a través del .Returns ". En los ejemplos de QS, un ejemplo es que hacen que el valor que se devuelve aumente cada vez.

En general , no necesitará un mecanismo como este muy a menudo (xUnit Test Patterns tiene términos para los antipatrones de las pruebas de lógica condicional de la clase ilk), y si hay alguna manera más simple o integrada de establecer lo que necesita, debe usarse en preferencia.

Part 3 of 4 in Justin Etheredge's Moq series lo cubre, y there's another example of callbacks here

+0

se olvidó de mencionar. Por supuesto que he visto su ejemplo, pero por alguna razón todavía no está claro para mí. avergonzado por decir, pero es cierto. – user9969

+0

¿Tal vez dar un ejemplo de código donde crees que lo necesitas y alguien puede conectar los puntos? –

+2

Hola Ruben Estoy aprendiendo Moq y si quieres estoy construyendo muchos ejemplos para entender cómo usarlo. Mi problema es que no entiendo cuándo usarlo. Una vez que entiendo el problema resuelto, escribiré mi propio código. Si tuvieras que explicarlo en tu propia palabra, ¿cuándo utilizarías la devolución de llamada? gracias aprecio su tiempo – user9969

44

He aquí un ejemplo del uso de una devolución de llamada para poner a prueba una entidad enviado a un servicio de datos que maneja una insertar.

var mock = new Mock<IDataService>(); 
DataEntity insertedEntity = null; 

mock.Setup(x => x.Insert(It.IsAny<DataEntity>())).Returns(1) 
      .Callback((DataEntity de) => insertedEntity = de); 

Sintaxis alternativa método genérico:

mock.Setup(x => x.Insert(It.IsAny<DataEntity>())).Returns(1) 
      .Callback<DataEntity>(de => insertedEntity = de); 

A continuación, se puede probar algo así como

Assert.AreEqual("test", insertedEntity.Description, "Wrong Description"); 
+2

Podría decirse que para ese caso en particular (dependiendo de si está tratando de expresar las pruebas contra el estado o el comportamiento), en algunos casos puede ser más limpio utilizar un 'It.Is 'en un' Mock.Verify' en lugar de ensuciar la prueba con temps. Pero +1 porque apuesto a que hay muchas personas que funcionarán mejor con un ejemplo. –

1

En la parte superior de las otras buenas respuestas aquí, yo he utilizado para realizar la lógica antes lanzando una excepción. Por ejemplo, necesitaba almacenar todos los objetos que se pasaron a un método para su posterior verificación, y ese método (en algunos casos de prueba) necesitó arrojar una excepción. Llamar al .Throws(...) en Mock.Setup(...) anula la acción Callback() y nunca la llama. Sin embargo, al lanzar una excepción dentro de la Devolución de llamada, aún puede hacer todas las cosas buenas que una devolución de llamada tiene para ofrecer, y aun lanzar una excepción.

6

Hay dos tipos de Callback en moq. Uno sucede antes de que regrese la llamada; el otro sucede después de que la llamada vuelve.

var message = ""; 
mock.Setup(foo => foo.Execute(arg1: "ping", arg2: "pong")) 
    .Callback((x, y) => 
    { 
     message = "Rally on!"; 
     Console.WriteLine($"args before returns {x} {y}"); 
    }) 
    .Returns(message) // Rally on! 
    .Callback((x, y) => 
    { 
     message = "Rally over!"; 
     Console.WriteLine("arg after returns {x} {y}"); 
    }); 

En ambos devoluciones de llamada, podemos:

  1. inspeccionar los argumentos del método
  2. arguemnts método
  3. captura
  4. cambio de estado del contexto
+0

En realidad, ambos suceden antes de que regrese la llamada (en lo que respecta a la persona que llama). Ver https://stackoverflow.com/a/28727099/67824. –

2

Callback es simplemente un medio para ejecutar cualquier costumbre código que desea cuando se realiza una llamada a uno de los métodos de prueba. Aquí hay un ejemplo simple:

public interface IFoo 
{ 
    int Bar(bool b); 
} 

var mock = new Mock<IFoo>(); 

mock.Setup(mc => mc.Bar(It.IsAny<bool>())) 
    .Callback<bool>(b => Console.WriteLine("Bar called with: " + b)) 
    .Returns(42); 

var ret = mock.Object.Bar(true); 
Console.WriteLine("Result: " + ret); 

// output: 
// Bar called with: True 
// Result: 42 

Recientemente me encontré con un caso de uso interesante para él. Supongamos que espera algunas llamadas a su simulacro, pero suceden al mismo tiempo. Por lo tanto, no tiene forma de saber el orden en el que los llamarán, pero desea saber si las llamadas que esperaba tuvieron lugar (independientemente de la orden). Se puede hacer algo como esto:

var cq = new ConcurrentQueue<bool>(); 
mock.Setup(f => f.Bar(It.IsAny<bool>())).Callback<bool>(cq.Enqueue); 
Parallel.Invoke(() => mock.Object.Bar(true),() => mock.Object.Bar(false)); 
Console.WriteLine("Invocations: " + String.Join(", ", cq)); 

// output: 
// Invocations: True, False 

Por cierto no se deje confundir por la engañosa "antes Returns" y "después Returns" distinción. Es meramente una distinción técnica de si su código personalizado se ejecutará después de que se haya evaluado Returns o antes. A los ojos de quien llama, ambos se ejecutarán antes de que se devuelva el valor. De hecho, si el método es void -retorno no puede llamar al Returns y, sin embargo, funciona igual. Para obtener más información, consulte https://stackoverflow.com/a/28727099/67824.

Cuestiones relacionadas