2010-02-19 14 views
10

tengo este problema, que puede ser un error en la burla de Rhino 3.5:Rhino ¿Se burla de los trozos de sobrescritura?

stubObj = MockRepository.GenerateStub(IObject); 

stubObj.Stub(a=>a.Get()).Return (Guid.Empty); //1.stub 
stubObj.Stub(a=>a.Get()).Return (Guid.NewGuid()); //2.stub, should overwrite the first one? 

esto:

var value = stubObj.Get(); 

vuelve Guid.Empty, es este el comportamiento correcto?

+0

yo no entiendo muy bien por qué quiere 'sobrescribir' una expectativa. El comportamiento me parece bien. Solo una especulación de mi parte: si está tratando de reutilizar o reciclar un talón para otra afirmación, entonces no debería hacer eso. Esa no sería una buena práctica para escribir pruebas. –

Respuesta

0

Las siguientes pruebas deben pasar:

// arrange 
var stubObj = MockRepository.GenerateStub<IObject>(); 
stubObj.Stub(a => a.Get()) 
     .Return(Guid.Empty); 
// act 
var value = stubObj.Get(); 
// assert 
Assert.AreEqual(Guid.Empty, value); 

Y si usted quiere devolver un nuevo GUID:

// arrange 
var stubObj = MockRepository.GenerateStub<IObject>(); 
stubObj.Stub(a => a.Get()) 
     .Return(Guid.NewGuid()); 
// act 
var value = stubObj.Get(); 
// assert 
Assert.AreNotEqual(Guid.Empty, value); 
+0

gracias, pero no quiero arreglarlo una vez más solo para cambiar el valor de retorno aplastado. ¿Existe algún tipo de método de reproducción() que reproduzca solo el objeto stub especificado? – David

1

acaba de programar el objeto de código auxiliar para dos llamadas separadas. Si llama a stubObj.Get nuevamente, debe obtener lo que Guid.NewGuid generó. Puede preparar su objeto falso para cualquier cantidad de invocaciones de diferentes tipos. Por este motivo, no tiene sentido esperar que la última llamada .Stub para una invocación determinada reemplace los llamados .Stub anteriores de esa llamada.

En su código de prueba, que debe ser breve y ordenado, nunca debería haber un caso en el que deba 'deshacer' tal programación del simulacro en la forma en que parezca querer hacerlo.

Si lo que debe devolverse es una cuestión condicional que varía según otros bits del código de prueba en varias llamadas a este bloque de código, lo último que desea es que la magia haga que los lectores tengan que descubrir qué significado. Si es condicional, debes aclararlo.

Y luego, cuando se ha dejado claro, refactorearlo como usted no debe tener lógica condicional en las pruebas (véase Patrones de prueba xUnit)

+0

a nitpick: 'Stub' solo establece el comportamiento, no las expectativas.Es desafortunado que RhinoMocks admita tanto record-replay-verify (donde registraría expectativas) como arrange-act-assert (donde usaría stubs y assertions separados), hace las cosas muy complicadas de explicar. –

+0

@wcoenen: No uso RhinoMocks, y la confusión y la confusión causadas por los múltiples modelos y otros restos heredados son la razón principal (elijo Moq ya que tiene una opinión). Lo principal que quería transmitir en mi respuesta fue que, en general, usted se está preparando para múltiples llamadas y, por lo tanto, sería sorprendente en la mayoría de los casos que el marco los englobe a todos en la forma en que el interrogador parece Sugerir que tendría sentido). Me complace que cualquiera entre y edite mi terminología para que sea menos confusa para los usuarios de RM. –

+0

@wcoenen: Intenté eliminar el uso indebido de la terminología de RM reemplazándola por terminología genérica y agradecería cualquier edición adicional para que las cosas no sean tan confusas. (Estaba leyendo el capítulo 6 o el libro Unit Testing de PragProg [publicado en 2007] en los últimos días, que relega a RhinoMocks a una barra lateral [y no menciona Moq], lo que no ayudará con la terminología.) (Sigo sobre mi punto principal, que es ese no debería estar modificando una configuración stub/mock como parte de una prueba o de lo contrario participar en cualquiera de los antipatrones de prueba de lógica condicional.) –

8

Si desea devolver el GUID una serie vacía conocido de veces , lo único que tienes que hacer es decirle a RhinoMocks cuántas veces se debe repetir, por ej. la siguiente prueba pasa:

[Test] 
    public void MultipleStubsTest() 
    { 
     var testMock = MockRepository.GenerateMock<ITest>(); 
     testMock.Stub(x => x.Get()).Return(Guid.Empty).Repeat.Once(); 
     testMock.Stub(x => x.Get()).Return(Guid.NewGuid()); 

     Assert.AreEqual(Guid.Empty, testMock.Get()); 
     Assert.AreNotEqual(Guid.Empty, testMock.Get()); 
    } 

si usted no sabe cuántas veces Get() será llamado ante el GUID debe cambiar, que siempre se puede utilizar .No() y el código de allí (por favor me deje saber si necesitas más detalles).

+0

Me gustaría ** som ** más detalles sobre cómo puedo usar 'Do()' if No sé el número de veces que se llamará a 'Get()'. No puedo reemplazar 'testMock' con un nuevo simulacro, así que en su lugar tengo que cambiar el valor que devuelve' Get() '. – smoksnes

+0

No importa. Encontré la respuesta aquí. http://stackoverflow.com/questions/13918281/why-cant-i-change-the-return-value-in-a-rhino-mocks-stub-object – smoksnes

1

Así es como lo harías. Pasa en mi máquina.

[TestMethod] 
    public void Test() 
    { 
     stubObj = MockRepository.GenerateMock<IGuidTest>(); 

     stubObj.Stub(a => a.Get()).Repeat.Times(1).Return(Guid.Empty); 
     stubObj.Stub(a => a.Get()).Repeat.Times(1).Return(Guid.NewGuid()); 

     Assert.AreEqual(Guid.Empty, stubObj.Get()); 
     Assert.AreNotEqual(Guid.Empty, stubObj.Get()); 

    } 
    public IGuidTest stubObj; 
    public interface IGuidTest 
    { 
     Guid Get(); 
    } 
-1

Sí, este es el comportamiento esperado. Escribir las expectativas/stubs de esa manera le dice al marco burlón que devuelva Guid.Empty la primera vez que se llama al método Get() y devuelve Guid.NewGuid() la segunda vez que se invoca.

Estas son algunas maneras de "sobrescribir" la primera expectativa con la segunda: How to change behaviour of stubs?

+0

NO, sin .Repetir.Una opción , stub devuelve solo el primer stub (Empty) y nunca el segundo (nuevo). –

Cuestiones relacionadas