2010-03-05 10 views
20

¿Es correcto que los stubs y burlas de Rhino Mocks solo sirvan para interfaces, no para clases concretas? Pasé bastante tiempo tratando de hacer funcionar este código. No esperaba que el trobado pubSubClient llamara siempre al método Send de la clase. Ese método tiene algunas dependencias y arroja una excepción.Los trozos y burlas de Rhino Mocks solo son buenos para las interfaces?

[Test] 
public void Test01() 
{ 
    PubSubMessage psm = new PubSubMessage(); 
    var pubSubClient = MockRepository.GenerateStub<PubSubClient>(); 
    pubSubClient.Stub(x => x.Send(psm)).IgnoreArguments().Return(null); 
    // actual PubSubClient Send method throws exception 
    // the rest of the test is skipped... 
} 

Sin embargo, cuando he extraído la interfaz y ejecutar la misma prueba con IPubSubClient, parece estar funcionando como se esperaba.

¿Significa que tengo que extraer la interfaz para cada clase que quiera simular/resguardar con Rhino? ¿O me falta algo, técnica o conceptualmente?

ACTUALIZACIÓN: OK, parece que me di cuenta de lo que me estaba perdiendo parte: burla de Rhino no puede interceptar las llamadas a métodos no virtuales. Entonces, supongo que tengo interfaces de uso o hago que todos los métodos de la clase concreta sean virtuales. Por favor corrígeme si hay otra opción.

Respuesta

23

La respuesta de Bryan del uso de simulaciones parciales es incorrecta. Para eso no son los simulacros parciales.

La respuesta de Jon Erickson es en su mayoría correcta: Rhino Mocks y Moq no pueden interceptar llamadas no virtuales, ni pueden interceptar métodos o propiedades estáticos. Eso significa que no puede falsificar lo siguiente:

DateTime.Now; // static property, can't fake static property 
someClass.SomeNonVirtualMethod(); // can't fake non-virtual method 
sealedClass.Foo(); // can't fake anything on sealed classes 
Utilities.SomeStaticMethod(); // can't fake static methods 
someList.Any(); // can't fake extension methods like Linq's .Any() 

TypeMock puede fingir esto, como mencionó Jon.

Cabe señalar que existe un marco de burla adicional que puede interceptar todas las llamadas: el Microsoft Moles framework. Funciona de la misma manera que TypeMock, usa la API .NET Profiler para interceptar llamadas.

Moles es gratis (por ahora). También es beta. Los lunares solo funcionan con Microsoft Pex tools. Y su API es claramente inferior a la API refinada y elegante de TypeMock.

+4

Si declara que las burlas parciales no son para algo, es más útil decir para qué son en su respuesta. Los simulacros parciales tienen la intención de burlarse solo de Parte de una clase, esto los hace prácticos (y necesarios) para burlarse de una clase de Resumen donde un simulacro normal no puede manejar esto. Esto permite la prueba de métodos abstractos. Un simulacro parcial (al menos en Rhino) se burlará de cualquier clase y no está restringido a las clases abstractas, tenga en cuenta, sin embargo, si hay un código de implementación que se invocará en el momento de la devolución. –

+0

(alerta de necro): ¡Acabo de descubrir que tu clase ni siquiera necesita ser abstracta para que los métodos sean virtuales! Una cosa tan pequeña, pero nunca la he considerado antes :-) – Heliac

1

Los simulacros parciales le permiten simular la funcionalidad de una clase concreta. Ver: http://www.ayende.com/wiki/Rhino+Mocks+Partial+Mocks.ashx

+0

Me temo que las burlas parciales no hacen exactamente eso. Son útiles para burlarse de algunos métodos no implementados en clases abstractas, pero si hay implementación, todavía se llama. En otras palabras, en mi ejemplo, reemplazar MockRepository.GenerateStub () con MockRepository.GeneratePartialMock () no cambia nada. –

+1

haga que su método sea virtual. –

3

Tienes que hacer que los métodos sean virtuales. Rhino se burla (y la mayoría de los demás marcos de aislamiento) utiliza clases proxy para crear los stubs/mocks.

Si utiliza Typemock aislador que puede burlarse de nada porque este marco aislamiento utiliza la API .NET de perfiles con el fin de crear sus talones/burla

+0

+1. Como el OP mencionó en su actualización, los métodos tienen que ser virtuales. Esto también es cierto para Moq y (creo) para todos los frameworks de aislamiento de .NET excepto TypeMock Isolator. La solución económica y sencilla es hacer que los métodos sean virtuales (o extraer una interfaz). – TrueWill

0

No creo que hay otra forma de hacerlo que no sea haciendo cualquier método que quieras simular virtual: creo que la manera en que se crean los buriles de las clases concretas es subclasificando dinámicamente la clase concreta que se burla y luego anulando los métodos dados con el comportamiento que especifiques en la prueba, por lo que esto requiere un método virtual para trabajar correctamente

2

Eso es esencialmente correcto, y en general es una buena práctica. Sin embargo, solo es realmente útil para un tipo específico de codificación.

No pienses en los objetos como cosas que una 'potencia superior' puede manipular. En cambio, piense en ellos como 'personas' autónomas que pueden enviarse mensajes entre sí. Una interfaz representa los mensajes enviados por un solo objeto.

A continuación, utiliza simulaciones para verificar que se enviaron los mensajes correctos, no para proporcionar implementaciones falsas de dependencias.

Lo ideal es que no cree una interfaz que coincida exactamente con una clase existente; en su lugar, la clase que consume la interfaz declara sus necesidades en forma de interfaz.

Cuestiones relacionadas