Поиск…


Непосредственная проверка порядка вызова

В тех случаях, когда метод, который должен быть протестирован, использует информацию из одного вызова для перехода к последующим вызовам, один подход, который можно использовать для обеспечения того, чтобы методы вызывались в ожидаемом порядке, заключается в настройке ожиданий, чтобы отразить этот поток данных.

Учитывая метод тестирования:

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

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

    _target.DoStuff(str);
}

Ожидания могут быть установлены для передачи данных из GetInitialValue через PrefixString и ReverseString в DoStuff , где информация проверяется. Если какой-либо из методов вызывается из строя, конечные данные будут ошибочными, и тест завершится с ошибкой.

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

Проверка порядка вызова с обратными вызовами

Если вы не можете / не хотите использовать Strict Mocks, вы не можете использовать MockSequence для проверки порядка вызова. Альтернативный подход заключается в использовании обратных вызовов для проверки того, что ожидания Setup ожидаются в ожидаемом порядке. Учитывая следующий метод проверки:

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

Его можно протестировать следующим образом:

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

Проверка порядка вызова с помощью MockSequence

Moq обеспечивает поддержку проверки порядка звонков с использованием MockSequence , однако он работает только при использовании Strict mocks. Итак, учитывая следующий метод проверки:

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

Его можно протестировать следующим образом:

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

В приведенном выше примере используется It.IsAny<string> при настройке ожиданий. Они могли использовать соответствующие строки («1111», «2222», «3333»), если требовались более точные соответствия.

Сообщение об ошибке, когда вызовы сделаны из последовательности, может быть немного ошибочным.

Строго. Все вызовы на макет должны иметь соответствующую настройку.

Это связано с тем, что каждое ожидание Setup рассматривается так, как будто оно не существует до тех пор, пока предыдущее ожидание в последовательности не будет выполнено.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow