moq
Oproeporder valideren
Zoeken…
Impliciet valideren van oproepvolgorde
Waar een te testen methode informatie uit één oproep gebruikt om door te geven aan volgende oproepen, is een benadering die kan worden gebruikt om ervoor te zorgen dat de methoden in de verwachte volgorde worden opgeroepen, het instellen van de verwachtingen om deze gegevensstroom weer te geven.
Gezien de te testen methode:
public void MethodToTest()
{
var str = _utility.GetInitialValue();
str = _utility.PrefixString(str);
str = _utility.ReverseString(str);
_target.DoStuff(str);
}
Verwachtingen kunnen worden ingesteld om gegevens van GetInitialValue
via PrefixString
en ReverseString
te DoStuff
aan DoStuff
, waar de informatie wordt geverifieerd. Als een van de methoden buiten gebruik wordt gesteld, zijn de eindgegevens onjuist en mislukt de test.
// 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));
Callorder valideren met callbacks
Wanneer u geen strikte mocks kunt / wilt gebruiken, kunt u MockSequence
niet gebruiken om de MockSequence
te valideren. Een alternatieve benadering is om callbacks te gebruiken om te valideren dat de Setup
verwachtingen worden opgeroepen in de verwachte volgorde. Gegeven de volgende testmethode:
public void MethodToTest()
{
_utility.Operation1("1111");
_utility.Operation3("3333");
_utility.Operation2("2222");
}
Het kan als volgt worden getest:
// 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"));
Oproeporder valideren met MockSequence
Moq biedt ondersteuning voor het valideren van oproepvolgorde met behulp van MockSequence
, maar het werkt alleen bij gebruik van strikte mocks. Dus, Gegeven de volgende testmethode:
public void MethodToTest()
{
_utility.Operation1("1111");
_utility.Operation2("2222");
_utility.Operation3("3333");
}
Het kan als volgt worden getest:
// 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"));
In het bovenstaande voorbeeld wordt It.IsAny<string>
bij het instellen van de verwachtingen. Deze hadden relevante tekenreeksen ("1111", "2222", "3333") kunnen gebruiken als er meer exacte overeenkomsten nodig waren.
De fout die wordt gerapporteerd wanneer gesprekken niet op volgorde worden geplaatst, kan een beetje misleidend zijn.
aanroep mislukt met schijngedrag Strict. Alle aanroepen op de mock moeten een overeenkomstige opstelling hebben.
Dit komt omdat elke Setup
verwachting wordt behandeld alsof deze niet bestaat totdat aan de vorige verwachting in de reeks is voldaan.