moq
Sprawdzanie poprawności kolejności połączeń
Szukaj…
Pośrednie sprawdzanie poprawności kolejności połączeń
W przypadku gdy metoda, która ma być testowana, wykorzystuje informacje z jednego połączenia do przekazania kolejnych połączeń, jednym z podejść, które można zastosować w celu zapewnienia, że metody są wywoływane w oczekiwanej kolejności, jest skonfigurowanie oczekiwań odzwierciedlających przepływ danych.
Biorąc pod uwagę metodę testowania:
public void MethodToTest()
{
var str = _utility.GetInitialValue();
str = _utility.PrefixString(str);
str = _utility.ReverseString(str);
_target.DoStuff(str);
}
Można ustawić oczekiwania na przekazywanie danych z GetInitialValue przez PrefixString i ReverseString do DoStuff , gdzie informacje są weryfikowane. Jeśli którakolwiek z metod zostanie wywołana poza kolejnością, dane końcowe będą nieprawidłowe i test zakończy się niepowodzeniem.
// Create mocks
var utilityMock = new Mock<IUtility>();
var targetMock = new Mock<ITarget>();
// Setup expectations, note that the returns value from one call matches the expected
// parameter for the next call in the sequence of calls we're interested in.
utilityMock.Setup(x => x.GetInitialValue()).Returns("string");
utilityMock.Setup(x => x.PrefixString("string")).Returns("Prefix:string");
utilityMock.Setup(x => x.ReverseString("Prefix:string")).Returns("gnirts:xiferP");
string expectedFinalInput = "gnirts:xiferP";
// Invoke the method to test
var sut = new SystemUnderTest(utilityMock.Object, targetMock.Object);
sut.MethodToTest();
// Validate that the final call was passed the expected value.
targetMock.Verify(x => x.DoStuff(expectedFinalInput));
Sprawdzanie poprawności kolejności połączeń za pomocą wywołań zwrotnych
Kiedy nie możesz / nie chcesz używać Strict Mocks, nie możesz używać MockSequence do sprawdzania kolejności połączeń. Alternatywnym podejściem jest użycie wywołań zwrotnych w celu sprawdzenia, czy oczekiwania Setup są wywoływane w oczekiwanej kolejności. Biorąc pod uwagę następującą metodę testowania:
public void MethodToTest()
{
_utility.Operation1("1111");
_utility.Operation3("3333");
_utility.Operation2("2222");
}
Można to przetestować w następujący sposób:
// Create the mock (doesn't have to be in strict mode)
var utilityMock = new Mock<IUtility>();
// Create a variable to track the current call number
int callOrder = 1;
// Setup each call in the sequence to be tested. Note that the callback validates that
// that callOrder has the expected value, then increments it in preparation for the next
// call.
utilityMock.Setup(x => x.Operation1(It.IsAny<string>()))
.Callback(() => Assert.AreEqual(1, callOrder++, "Method called out of order") );
utilityMock.Setup(x => x.Operation2(It.IsAny<string>()))
.Callback(() => Assert.AreEqual(2, callOrder++, "Method called out of order") );
utilityMock.Setup(x => x.Operation3(It.IsAny<string>()))
.Callback(() => Assert.AreEqual(3, callOrder++, "Method called out of order") );
// Invoke the method to be tested
var sut = new SystemUnderTest(utilityMock.Object);
sut.MethodToTest();
// Validate any parameters that are important, note these Verifications can occur in any
// order.
utilityMock.Verify(x => x.Operation2("2222"));
utilityMock.Verify(x => x.Operation1("1111"));
utilityMock.Verify(x => x.Operation3("3333"));
Sprawdzanie poprawności kolejności połączeń za pomocą MockSequence
Moq zapewnia obsługę sprawdzania poprawności kolejności połączeń przy użyciu MockSequence , jednak działa tylko przy użyciu ścisłych prób. Biorąc pod uwagę następującą metodę testowania:
public void MethodToTest()
{
_utility.Operation1("1111");
_utility.Operation2("2222");
_utility.Operation3("3333");
}
Można to przetestować w następujący sposób:
// Create the mock, not MockBehavior.Strict tells the mock how to behave
var utilityMock = new Mock<IUtility>(MockBehavior.Strict);
// Create the MockSequence to validate the call order
var sequence = new MockSequence();
// Create the expectations, notice that the Setup is called via InSequence
utilityMock.InSequence(sequence).Setup(x => x.Operation1(It.IsAny<string>()));
utilityMock.InSequence(sequence).Setup(x => x.Operation2(It.IsAny<string>()));
utilityMock.InSequence(sequence).Setup(x => x.Operation3(It.IsAny<string>()));
// Run the method to be tested
var sut = new SystemUnderTest(utilityMock.Object);
sut.MethodToTest();
// Verify any parameters that are cared about to the operation being orchestrated.
// Note that the Verify calls can be in any order
utilityMock.Verify(x => x.Operation2("2222"));
utilityMock.Verify(x => x.Operation1("1111"));
utilityMock.Verify(x => x.Operation3("3333"));
Powyższy przykład używa It.IsAny<string> podczas konfigurowania oczekiwań. Mogłyby one użyć odpowiednich ciągów („1111”, „2222”, „3333”), gdyby wymagane były dokładniejsze dopasowania.
Błąd zgłaszany podczas wykonywania połączeń poza kolejnością może być nieco mylący.
wywołanie nie powiodło się z fałszywym zachowaniem Strict. Wszystkie wywołania w makiecie muszą mieć odpowiednią konfigurację.
Jest tak, ponieważ każde oczekiwanie Setup jest traktowane tak, jakby nie istniało, dopóki poprzednie oczekiwanie w sekwencji nie zostanie spełnione.