2011-10-27 8 views
7

Używam Moq jako moje szydercze ramy i muszę przetestować klasę, że gdy określony typ wyjątku jest uruchomiony, będzie próbował do sytuacja zostanie rozwiązana, gdy dojdzie do zakończenia egzekucji.Jak zrobić makiety rzuca wyjątek za pierwszym razem i zwracają wartość drugi

Więc co potrzebne jest coś podobnego do:

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); 

dzięki za pomoc można dać.

Odpowiedz

15

Jest to metoda jednokierunkowa polegająca na zwracaniu różnych wartości dla każdego wywołania.

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()); 

Jeśli metoda zwraca void, przeznaczenie:

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

To wygląda interesująco, ale co, jeśli metoda jest nieważna i po instalacji nie otrzymam metody "Zwroty"? I faktycznie to działa, jeśli "GetCountThing" zwraca int, nie skompiluje się, jeśli zwróci coś innego. –

+0

@SergioRomero - zapoznaj się z edytowaną odpowiedzią. – TrueWill

+0

Jeśli nie jest to int, zmień to, co wracasz z linii 'Returns'. Nie musi to być wartość "połączeń". – TrueWill

1

Dlaczego nie faktycznie napisać swój własny obiekt testowy, który wykonuje to? Jeśli ma być używany tylko do testowania, coś takiego:

public class Mock : IFoo 
{ 
    private int _calls; 

    public Mock() 
    { 
     _calls = 0; 
    } 

    public int Execute() 
    { 
     _calls++; 

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

     return value; 

    } 

} 
+1

W tym przypadku mogłem to zobaczyć. Jest to jednak skrajny przypadek; przez większość czasu chcę albo kodu pośredniczącego, który zwróci znane stałe wartości, albo sztuczkę, która sprawdzi, czy dana metoda została wywołana. Moq bardzo ułatwia tworzenie obu tych elementów w locie. Ponadto, jeśli masz starszy interfejs z 30 członkami i potrzebujesz tylko jednego z nich do tego testu, rozwiązanie Moq jest znacznie krótsze. – TrueWill

Powiązane problemy