2011-09-22 5 views
7

Estoy tratando de confirmar que se ha llamado a un método en un talón. El método que estoy tratando de afirmar se llamó toma un IEnumerable<string>. No me importan los contenidos exactos, pero solo quiero probar que el recuento es un cierto número. No puedo conseguir la afirmación correcta, consigoRestricción de lista falsa de Rhino

Rhino.Mocks.Exceptions.ExpectationViolationException : Bob.DoThings(collection count equal to 10); Expected #1, Actual #0. 

Sé que DoThings() de hecho se está llamando ... simplemente no puede conseguir la restricción correcta ..

var myBob= MockRepository.GenerateStub<Bob>(); 
var countConstraint = Rhino.Mocks.Constraints.List.Count(Rhino.Mocks.Constraints.Is.Equal(10)); 

// execution code.... 
Joe myJoe = new Joe(myBob); 
myJoe.MethodThatShouldCallDoThingWith10(); 

myBob.AssertWasCalled(s => s.DoThings(null), o => Constraints(countConstraint)); 

I También he intentado agregar "IgnorarArgumentos" como una restricción. ¿Qué me estoy perdiendo?

Respuesta

11

El problema aquí es con la ejecución diferida. No es hasta que se enumere IEnumerable<string> que la lista de elementos se "construye". Como Rhino.Mocks simplemente registra lo que se llama, nunca "usa" los argumentos del método y, por lo tanto, la lista nunca se construye ni se enumera. Como ha visto, al agregar un ToList() o ToArray() enumera y crea la lista para que pase la prueba si usa uno de esos métodos.

Una solución consiste en agarrar la lista que se pasa al método y hacer su cheque en la que:

var list = (IEnumerable<int>) myBob.GetArgumentsForCallsMadeOn(b => b.DoThings(null))[0][0]; 
Assert.AreEqual(10, list.Count()); 

Esta prueba pasa y no requiere ningún cambio en su código.

+0

Patrick, I no estaba al tanto del método GetArgumentsForCallsMadeOn(). Pude escribir una afirmación significativa aquí. Los problemas de ejecución retrasada parecen estar surgiendo con frecuencia últimamente. Gracias. –

2

Este problema fue alredy informado Here. He sido capaz de reproducir este problema con la siguiente Bob y Joe:

public interface Bob 
{ void DoThings(IEnumrable<int> list); } 

public class Joe 
{ 
    private readonly Bob bob; 

    public Joe(Bob bob) 
    { this.bob = bob; } 

    public void MethodThatShouldCallDoThingWith10() 
    { 
      var values = Enumerable.Range(1, 100).Where(x => x > 0 && x < 11); 
      bob.DoThings(values); 
    } 
} 

Parece que hay algún problema en la burla de Rhino después de todo, cuando se trata de LINQ: o informar del fallo a Ayende o añadir ToList () en su código de producción (realmente no recomendado) ...

+0

Es extraño ... Si pongo un punto de interrupción en MethodThatShouldCallDoThingWith10, puedo ver que la instancia de bob es un proxy y está realizando la llamada. Obviamente este no es mi código verdadero aquí, pero sí, creo que hay algo dudoso en mi parte, pero no puedo señalarlo –

+0

Puede comenzar a simplificarlo ... ¿Bob es una interfaz? ¿Clase abstracta? Clase con método virtual? –

+0

Es una interfaz con un genérico ... un Bob . Me pregunto si la unidad bajo prueba está llamando a MethodThatShouldCallDoThingWith10 con un WhereSelectIterator , no es algo más básico como una lista o un simple IEnumerable . Estoy pensando que una restricción de Count no es tan indulgente? –