2010-10-25 15 views
5

Estoy haciendo las expectativas ordenadas en los simulacros de rinoceronte según lo descrito por ayende en this publicación. Mi código es como la siguiente:Reutilizando un simulacro verificado

using (_mocks.Ordered()) 
    { 
    Expect.Call(() => _myMock.CallA()); 
    Expect.Call(() => _myMock.CallB(40)); 
    Expect.Call(() => _myMock.CallA()); 
    } 
    _mocks.ReplayAll(); 
    _myObjectUnderTest.DoStuff(); 
    _mocks.VerifyAll(); 

Después de esto me gustaría añadir más expectativas y probar más de los métodos de mi objeto. Quiero hacer esto porque tengo algunos métodos de prueba básicos que configuran mi objeto de prueba, y no quiero tener que volver a probar esa funcionalidad, así que simplemente llamo al método de prueba anterior. Si intento agregar más expectativas después de VerifyAll() recibo una excepción: "Esta acción no es válida cuando el objeto simulado está en estado verificado".

Parte de mi problema es que realmente no entiendo lo que hace todo el material de reproducción/verificación, simplemente copié el código. Estoy usando simulacros estrictos, por lo que cualquier código de configuración debe tener expectativas coincidentes o falla. No quiero duplicar las expectativas para mi código de configuración.

¿Hay alguna manera de reiniciar el simulacro para estar listo para comenzar de nuevo de alguna manera?

Respuesta

4

Respuesta corta: no. Ahora a la respuesta larga.

Lo que hace la repetición y verificación de cosas es esto. Antes de llamar al ReplayAll, le está diciendo a Rhino lo que espera que hagan los métodos. En cierto sentido, estás grabando llamadas a los objetos simulados que has creado.

Después de haber grabado las llamadas al método, llame al ReplayAll diciéndole a Rhino que ahora va a hacer 'algo' que debería ejecutar los métodos tal como se grabaron.

Por último, llame al VerifyAll pidiéndole a Rhino que verifique si realmente se llamaron los métodos tal como los grabó.

Ahora vamos a por qué realmente no debería querer volver a utilizar los simulacros. Con las pruebas unitarias/TDD, la prueba de su unidad debe probar lo menos posible. Esto es para mantener sus pruebas unitarias simples y transparentes. La idea general de las pruebas unitarias es que muchas muchas pruebas pequeñas como un todo prueban todo el sistema.

Para una muy buena presentación sobre TDD que explica este y otros temas, vea http://www.infoq.com/presentations/integration-tests-scam.

PD: Un pequeño detalle: Mientras que los métodos no devuelven un resultado, se puede escribir:

using (_mocks.Ordered()) 
{ 
    Expect.Call(() => _myMock.CallA()); 
    Expect.Call(() => _myMock.CallB(40)); 
    Expect.Call(() => _myMock.CallA()); 
} 

como:

using (_mocks.Ordered()) 
{ 
    _myMock.CallA(); 
    _myMock.CallB(40); 
    _myMock.CallA()); 
} 

(al menos con la última versión de Rhino)

+0

El problema viene cuando quiero probar B, pero se debe llamar a A para configurar todo para B primero. Si A llama a métodos en mi simulacro, entonces debo esperarlos o usar simulacros dinámicos en lugar de simulacros estrictos. Me gustaría no duplicar todas las expectativas, porque ya he probado a fondo A. – captncraig

+1

Sí, tengo ese problema también. Tienes dos opciones. El primero es modificar la lógica de su negocio para que pueda controlar qué partes se activan o si divide su lógica comercial en partes más pequeñas que evalúe de manera independiente.La segunda opción es elevar algunas expectativas a un método privado de su '[TestFixture]' y llamar eso en ambas pruebas. Hice el último (por ahora). –

+0

-1 ya que tenía este problema, pero encontré un camino que niega esta respuesta (ver otra publicación - "respuesta corta: sí") – brewmanz

0

respuesta corta: sí

más larga respuesta: Pruebe lo siguiente

[Test] 
    public void RhinoMock_PerformMultipleChecks() 
    { 
     var myMock = MockRepository.GenerateDynamicMockWithRemoting<IComparable>(); 

     // first round of checks 
     myMock.Expect(x => x.CompareTo("123")).Return(1); 
     myMock.Expect(x => x.CompareTo("-12")).Return(-1); 
     Assert.AreEqual(1, myMock.CompareTo("123")); 
     Assert.AreEqual(-1, myMock.CompareTo("-12")); 
     myMock.VerifyAllExpectations(); 

     // reset 
     myMock.BackToRecord(); 
     myMock.Replay(); 

     // next round of checks 
     myMock.Expect(x => x.CompareTo(1.23)).Return(1); 
     myMock.Expect(x => x.CompareTo(-12)).Return(-1); 
     Assert.AreEqual(1, myMock.CompareTo(1.23)); 
     Assert.AreEqual(-1, myMock.CompareTo(-12)); 
     myMock.VerifyAllExpectations(); 

     // reset 
     myMock.BackToRecord(); 
     myMock.Replay(); 

     // final round of checks 
     myMock.Expect(x => x.CompareTo(1.23m)).Return(1); 
     myMock.Expect(x => x.CompareTo(-12m)).Return(-111); 
     Assert.AreEqual(1, myMock.CompareTo(1.23m)); 
     Assert.AreEqual(-111, myMock.CompareTo(-12m)); 
     myMock.VerifyAllExpectations(); 
    } 
Cuestiones relacionadas