Recherche…


Validation implicite de l'ordre d'appel

Lorsqu'une méthode à tester utilise des informations provenant d'un appel pour les transmettre aux appels suivants, une méthode permettant de s'assurer que les méthodes sont appelées dans l'ordre prévu consiste à configurer les attentes pour refléter ce flux de données.

Étant donné la méthode à tester:

public void MethodToTest()
{
    var str = _utility.GetInitialValue();

    str = _utility.PrefixString(str);
    str = _utility.ReverseString(str);

    _target.DoStuff(str);
}

Les attentes peuvent être définies pour transmettre des données de GetInitialValue via PrefixString et ReverseString à DoStuff , où les informations sont vérifiées. Si l'une des méthodes est appelée hors service, les données de fin seront erronées et le test échouera.

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

Validation de l'ordre d'appel avec des rappels

Lorsque vous ne pouvez pas / ne voulez pas utiliser Strict Mocks, vous ne pouvez pas utiliser MockSequence pour valider l'ordre des appels. Une autre approche consiste à utiliser des rappels pour valider que les attentes de Setup sont invoquées dans l'ordre prévu. Étant donné la méthode suivante pour tester:

public void MethodToTest()
{
    _utility.Operation1("1111");
    _utility.Operation3("3333");
    _utility.Operation2("2222");
}

Il peut être testé comme suit:

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

Validation de l'ordre d'appel avec MockSequence

Moq prend en charge la validation de l'ordre d'appel à l'aide de MockSequence , mais ne fonctionne que lorsque vous utilisez des MockSequence strictes. Donc, étant donné la méthode suivante pour tester:

public void MethodToTest()
{
    _utility.Operation1("1111");
    _utility.Operation2("2222");
    _utility.Operation3("3333");
}

Il peut être testé comme suit:

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

L'exemple ci-dessus utilise It.IsAny<string> lors de la configuration des attentes. Ceux-ci auraient pu utiliser des chaînes pertinentes ("1111", "2222", "3333") si des correspondances plus précises étaient requises.

L'erreur signalée lorsque les appels sont effectués hors séquence peut être un peu trompeuse.

invocation échouée avec un comportement simulé Strict. Toutes les invocations sur le simulacre doivent avoir une configuration correspondante.

En effet, chaque attente d' Setup est traitée comme si elle n'existait pas jusqu'à ce que l'attente précédente de la séquence soit satisfaite.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow