2010-02-16 30 views
6

Si tuviera que escribir una biblioteca burlona, ​​¿cómo funcionaría esto (en otras palabras, ¿cómo "funcionan?)?¿Cómo funcionan los frameworks simulados?

Una de las cosas que me pregunto es que siempre está estableciendo expectativas, así que realmente necesita para comparar la expectativa con lo que hace el método en tiempo de ejecución, así que supongo que se requiere reflexión (resolver tipos en tiempo de ejecución)

Además, cuando se utiliza el término "objeto simulado", ¿se rompe el objeto o sería un objeto con expectativas preestablecidas?

Cuando pienso en cómo escribiría mi propia implementación de un framework/técnica, como objetos simulados, me doy cuenta de cuánto sé realmente (o no saber) y en qué me tropezaría: si el objeto simulado está preprogramado para devolver las expectativas establecidas y no llama al objeto real real, ¿no sería el resultado siempre el mismo? Por ejemplo:

[TestMethod, Isolated] 
public void FakeReturnValueByMethodArgs() 
{ 
    var fake = Isolate.Fake.Instance<ClassToIsolate>(); 
    // MethodReturnInt will return 10 when called with arguments 3, "abc" 
    Isolate.WhenCalled(()=> fake.MethodReturnInt(3, "  abc")).WithExactArguments().WillReturn(10); 
// MethodReturnInt will return 50 when called with arguments 3, "xyz" 
    Isolate.WhenCalled(()=> fake.MethodReturnInt(3, "xyz")).WithExactArguments().WillReturn(50); 

    Assert.AreEqual(10, fake.MethodReturnInt(3, "abc")); 
    Assert.AreEqual(50, fake.MethodReturnInt(3, "xyz")); 

}

¿No esto siempre de vuelta verdad?

Respuesta

8

La idea de los frameworks burlones es burlarse de las dependencias, y no de las clases reales bajo prueba. Para su ejemplo, su prueba siempre será verdadera, ¡porque realmente solo está probando el marco de burla y no su código real!

Una maqueta mundo real se vería más como esto:

[TestMethod, Isolated] 
public void FakeReturnValueByMethodArgs() { 
    var fake = Isolate.Fake.Instance<DependencyClass>(); 
    // MethodReturnInt will return 10 when called with arguments 3, "abc" 
    Isolate.WhenCalled(()=> fake.MethodReturnInt(3, "abc")).WithExactArguments().WillReturn(10); 

    var testClass = new TestClass(fake); 
    testClass.RunMethod(); 

    // Verify that the setup methods were execute in RunMethod() 
    // Not familiar with TypeMock's actual method to do this... 
    IsolatorExtensions.VerifyInstanceWasCalled(fake); 

    // Or assert on values 
    Assert.AreEqual(10, testClass.AProperty); 
} 

Observe cómo se pasa la maqueta en el TestClass y un método run en él.

Puede leer The Purpose of Mocking para tener una mejor idea de cómo funciona la burla.


Actualización: explicación de por qué se está probando sólo el marco de burla:

Lo que hemos hecho es crear un método MethodReturnInt con el marco de burla usando Isolate.WhenCalled().Cuando se llama a MethodRecturnInt en la aserción, el código se ejecutará el delegado () => fake.MethodReturnInt() y volver 10. El marco de burla está creando efectivamente un método (aunque de forma dinámica) que sería algo como esto:

public void MethodReturnInt(int value, string value2) { 
    Assert.Equal(3, value); 
    Assert.Equal("abc", value2); 
    return 10; 
} 

Es un poco más complicado que eso, pero esta es la idea general. Como nunca ejecuta ningún otro código que no sea la creación de 2 métodos y luego afirma esos dos métodos, no está probando su propio código y, por lo tanto, solo está probando el marco de burla.

+0

Gracias. ¿Puedes explicar cómo el código que proporcioné prueba el marco burlón y el código real (tal vez soy un poco lento)? – dotnetdev

+0

Gracias por eso. Puede que tenga un método que se basa en una determinada fecha/hora para realizar una acción, pero ¿qué sucede si mi método realmente devuelve la hora actual (la esencia del método es algo que generalmente se burla)? ¿Cómo pruebo esto? Si un método hace algo a las 12 a. M., Pruebo el "algo" que hace, pero ¿qué ocurre si mi método devuelve el tiempo? ¿Cómo lo pruebo? – dotnetdev

+0

@dotnetdev - Eche un vistazo a esta pregunta ASÍ: http://stackoverflow.com/questions/565289/unit-testing-code-that-does-date-processing-based-on-todays-date/565314#565314 Efectivamente necesitas romper la dependencia de DateTime en tu código –

0

Sí, siempre será cierto. Los objetos simulados se deben usar cuando la clase en prueba requiera otra implementación de clase que no desee involucrar en la ejecución de la prueba. Esto es más útil cuando se trata de una clase que usa interfaces con múltiples implementaciones, o hay servicios complejos/costosos/externos que no desea configurar.

En el código anterior, te estás burlando de la clase que estás "probando".

Otra forma de pensar es que los comportamientos simulados que registra son aserciones de Black Box (implementación), donde Assert.* son aserciones de la caja blanca (api).

+0

Visto de otra manera, los objetos simulados son solo otra capa de direccionamiento indirecto por encima del retorno (verdadero) o comentando que tendrías que usar en su lugar. –

0

Tiene la idea correcta. A menudo encontrará que tienen un par de modos de operación. Si te preocupa que tu método no se llame o no se llame en el orden correcto, con frecuencia hay un modo "estricto" que provoca que el marco simulado genere una excepción si no se llama al método antes de que finalice el proceso. prueba, o se llama con los parámetros incorrectos, etc.

La mayoría de los marcos han pensado en ese tipo de problemas, por lo que solo debe averiguar cómo configurarlo para su escenario.

0

Una forma de ver cómo funciona el sistema simulado es simplemente mirar en los momentos cuando se necesita un objeto pero no se quiere usar la clase real, sino que se quiere dar algún tipo específico de datos que no t (o no lo hará de manera confiable). Entonces, si ves:

Assert.IsTrue(myLogic.IsNoon(time)) 

puedes ver cómo la afirmación querría que el objeto de tiempo siempre fuera el mediodía. . . bueno, no puedes hacer eso con un objeto real de manera confiable. Entonces necesitas un suplente. Puedes hacer una clase falsa solo para la prueba, pero eso es algo pesado. Los marcos falsos son un atajo.