2011-10-27 14 views
7

Estoy usando Moq como mi marco burlón y necesito probar una clase que cuando se ejecuta un tipo específico de excepción seguirá intentando hasta la situación se resuelve una vez que eso sucede, la ejecución termina.Cómo hacer un simulacro lanza una excepción la primera vez y devuelve un valor el segundo

Así que lo que necesito es algo similar a:

myMock = Mock<IFoo>(); 

myMock.Setup(m => m.Excecute()).Throws<SpecificException>(); 
myMock.Setup(m => m.Execute()); 

var classUnderTest = MyClass(myMock); 
classUnderTest.DoSomething(); 

Assert.AreEqual(expected, classUnderTest.Result); 

Gracias por cualquier ayuda que puede dar.

Respuesta

15

Esta es una manera, basada en el ejemplo Moq QuickStart de devolver valores diferentes en cada invocación.

var mock = new Mock<IFoo>(); 
var calls = 0; 
mock.Setup(foo => foo.GetCountThing()) 
    .Returns(() => calls) 
    .Callback(() => 
    { 
     calls++; 
     if (calls == 1) 
     { 
      throw new InvalidOperationException("foo"); 
     } 
    }); 

try 
{ 
    Console.WriteLine(mock.Object.GetCountThing()); 
} 
catch (InvalidOperationException) 
{ 
    Console.WriteLine("Got exception"); 
} 

Console.WriteLine(mock.Object.GetCountThing()); 

Si el método devuelve void, utilice:

var myMock = new Mock<IFoo>(); 
bool firstTimeExecuteCalled = true; 

myMock.Setup(m => m.Execute()) 
     .Callback(() => 
     { 
      if (firstTimeExecuteCalled) 
      { 
       firstTimeExecuteCalled = false; 
       throw new SpecificException(); 
      } 
     }); 

try 
{ 
    myMock.Object.Execute(); 
} 
catch (SpecificException) 
{ 
    // Would really want to call Assert.Throws instead of try..catch. 
    Console.WriteLine("Got exception"); 
} 

myMock.Object.Execute(); 
Console.WriteLine("OK!"); 
+0

Parece interesante pero, ¿qué pasa si el método es nulo y no aparece el método "Devoluciones" después de la configuración? Y en realidad esto funciona si "GetCountThing" devuelve un int, no se compilará si devuelve algo más. –

+0

@SergioRomero - por favor vea la respuesta editada. – TrueWill

+0

En cuanto a si no es una int, cambie lo que está devolviendo de la línea 'Returns'. No tiene que ser el valor de 'calls'. – TrueWill

1

Por qué no escribir en realidad su propio objeto de prueba que hace esto? Si se va a utilizar para pruebas, es decir algo como:

public class Mock : IFoo 
{ 
    private int _calls; 

    public Mock() 
    { 
     _calls = 0; 
    } 

    public int Execute() 
    { 
     _calls++; 

     if (_calls == 1) 
      throw new Exception(); 

     return value; 

    } 

} 
+1

En este caso pude ver eso. Este es un caso marginal, sin embargo; la mayor parte del tiempo, o quiero un stub que devolverá valores constantes conocidos o un simulacro que verificará que se haya llamado a un método determinado. Moq hace que sea muy fácil crear ambos sobre la marcha. Además, si tiene una interfaz heredada con 30 miembros y solo necesita uno para esta prueba, la solución de Moq es mucho más corta. – TrueWill

Cuestiones relacionadas