2009-09-17 4 views
14

Soy nuevo en Moq y estoy aprendiendo.Moq: especificar los valores de devolución como parte de las expectativas

Necesito comprobar que un método devuelve el valor esperado. He creado un ejemplo de noddy para explicar mi problema. Esta falla estrepitosamente con:

"ArgumentException: La expresión no es una invocación de método: c => (c.DoSomething (" Jo " "blog", 1) = "OK")"

¿Puedes corregir lo que estoy haciendo mal?

[TestFixtureAttribute, CategoryAttribute("Customer")] 
public class Can_test_a_customer 
{ 
    [TestAttribute] 
    public void Can_do_something() 
    { 
     var customerMock = new Mock<ICustomer>(); 

     customerMock.Setup(c => c.DoSomething("Jo", "Blog", 1)).Returns("OK"); 

     customerMock.Verify(c => c.DoSomething("Jo", "Blog", 1)=="OK"); 
    } 
} 

public interface ICustomer 
{ 
    string DoSomething(string name, string surname, int age); 
} 

public class Customer : ICustomer 
{ 
    public string DoSomething(string name, string surname, int age) 
    { 
     return "OK"; 
    } 
} 

En pocas palabras: si quería probar un método similar a la anterior, y sé que estoy esperando volver un "OK", ¿cómo iba a escribirlo usando Moq?

Gracias por cualquier sugerencia.

Respuesta

15
  1. Se necesita un sujeto de prueba que interactúa con objetos simulados (a menos que usted está escribiendo una prueba aprendiz de Moq.) Escribí una simple continuación
  2. expectativas de ajustes Es en el objeto de burla, que especifica la exacta argumentos (estrictos - si desea por supuesto, de lo contrario usar Is.Any<string> a aceptar cualquier cadena) y especificar valores de retorno en su caso
  3. su sujeto de prueba (como parte de la etapa Acta de la prueba) llamará en su maqueta
  4. usted afirmar que el sujeto de prueba se comportó como se requiere. El sujeto de la prueba usará el valor de retorno de los métodos simulados; verifíquelo a través de la interfaz pública del sujeto de prueba.
  5. También verifica que se cumplieron todas las expectativas que especificó; de hecho, todos los métodos que esperaba que se llamaran se llamaron.

.

[TestFixture] 
public class Can_test_a_customer 
{ 
    [Test] 
    public void Can_do_something() 
    { 
    //arrange 
    var customerMock = new Moq.Mock<ICustomer>(); 
    customerMock.Setup(c => c.DoSomething(Moq.It.Is<string>(name => name == "Jo"), 
     Moq.It.Is<string>(surname => surname == "Blog"), 
     Moq.It.Is<int>(age => age == 1))) 
     .Returns("OK"); 

    //act 
    var result = TestSubject.QueryCustomer(customerMock.Object); 

    //assert 
    Assert.AreEqual("OK", result, "Should have got an 'OK' from the customer"); 
    customerMock.VerifyAll(); 
    } 
} 

class TestSubject 
{ 
    public static string QueryCustomer(ICustomer customer) 
    { 
    return customer.DoSomething("Jo", "Blog", 1); 
    } 
} 
+1

Exactamente. Su prueba no tiene sujeto de prueba, lo que ha llevado a la confusión. Usted prueba un sujeto de prueba, no un simulacro. –

+0

Estoy aprendiendo también, creo que tengo mi cabeza alrededor de esto, lo confirmaría por favor. En este ejemplo, 'DoSomething' podría devolver' jabberwocky', pero porque a su '// arrange .Setup' se le dice' .Return ("OK") 'esa es la afirmación. Entiendo que la prueba es para asegurarme de que 'TestSubject' funciona como se espera, y no hay una prueba en' Customer' aquí. Si ese es el caso, ¿por qué afirmar el valor de retorno de 'Cliente' y no simplemente' .Returns ("SUCCESS") 'o alguna otra cadena genérica para verificar que' TestSubject' se haya completado con éxito? – JabberwockyDecompiler

+0

@JabberwockyDecompiler: era solo una prueba de muestra en la que la salida depende de un colaborador (burlado) ... por ejemplo, el cliente podría devolver "Sam" y el método/clase bajo prueba podría devolver "¡Hola, Sam!". Para probar esto: necesitaría configurar el simulacro para devolver "Sam" en la prueba. – Gishu

11

Mock<T>.Verify no devuelve el valor que devuelve la llamada al método, por lo que no puede simplemente compararlo con el valor esperado con "==".

De hecho, hay no overload of Verify que devuelve algo, ya que nunca debería necesitar verificar que un método simulado devuelve un valor específico. ¡Después de todo, usted fue responsable de configurarlo para devolver ese valor en primer lugar! Los valores de devolución de los métodos burlados están ahí para ser utilizados por el código que está probando, no está probando los simulacros.

Use Verificar para confirmar que se invocó el método con los argumentos que esperaba, o que a una propiedad se le asignó el valor que esperaba. Los valores de retorno de los métodos y propiedades burlados no son importantes para cuando llega a la fase "afirmar" de su prueba.

2

Usted está haciendo lo mismo que este chico estaba haciendo aquí: How to Verify another method in the class was called using Moq

Usted está burlando de lo que se está probando. Esto no tiene sentido. El uso de Mocks es para el aislamiento. Su prueba Can_Do_Something siempre pasará. No importa qué. Esta no es una buena prueba.

Eche un vistazo más de cerca a la prueba de Gishu o la prueba que propuse en la pregunta SO vinculada.

+0

Hola, tienes toda la razón, soy nuevo en el mundo de la burla Así que es correcto decir que burlarse de un método es solo para verificar que se llamó al método o se estableció una propiedad para no verificar qué devuelve el método. ¿Es esto correcto? –

+1

Un simulacro está diseñado para verificar un método externo Y aísle el código que está * realmente * probando. Por ejemplo, si su clase intentó acceder a una base de datos, se burlaría de su clase de acceso a los datos para que no solo devolviera resultados consistentes, sino que su prueba no requiriera la ejecución de una base de datos. Está aislando la clase que está probando de otros cambios en otras clases que podría realizar. –

Cuestiones relacionadas