使用 MockSequence 验证呼叫顺序

Moq 支持使用 MockSequence 验证呼叫顺序,但只有在使用严格模拟时才有效。因此,给出以下测试方法:

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>。如果需要更精确的匹配,这些可能使用了相关的字符串(111122223333)。

在不按顺序进行调用时报告的错误可能有点误导。

调用失败,模拟行为严格。模拟上的所有调用都必须具有相应的设置。

这是因为,每个 Setup 期望被视为好像它不存在,直到满足序列中的先前期望。