验证单元测试中的函数调用顺序

时间:2013-04-18 14:14:40

标签: unit-testing nsubstitute fluent-assertions

我想要一个单元测试,以正确的顺序验证2个函数调用。在该示例中,第一个函数加密文件并将其保存到文件系统,第二个函数将加密文件发送到第三方处理器(通过FTP)。

我使用NSubstitute作为模拟框架和FluentAssertions来帮助进行测试验证。看起来这不是你可以通过开箱即用的NSubstitute实现的。

public void SendUploadToProcessor(Stream stream, string filename)
{
    var encryptedFilename = FilenameBuilder.BuildEncryptedFilename(filename);
    FileEncrypter.Encrypt(stream, filename, encryptedFilename);
    FileTransferProxy.SendUpload(encryptedFilename);
}

[TestMethod, TestCategory("BVT")]
public void TheEncryptedFileIsSent()
{
    var stream = new MemoryStream();
    var filename = Fixture.Create<string>();

    var encryptedFilename = Fixture.Create<string>();
    FilenameBuilder
        .BuildEncryptedFilename(Arg.Any<string>())
        .Returns(encryptedFilename);

    Sut.SendUploadToProcessor(stream, filename);

    // Something here to verify FileEncrypter.Encrypt() gets called first

    FileTransferProxy
        .Received()
        .SendUpload(encryptedFilename);
}

2 个答案:

答案 0 :(得分:3)

NSubstitute.Experimental命名空间中尝试Received.InOrder

像这样(我没有测试过这个):

Received.InOrder(() => {
  FileEncrypter.Encrypt(stream, filename, encryptedFilename);
  FileTransferProxy.SendUpload(encryptedFilename);
});

如果您不习惯依赖实验性功能,则需要设置回调以按顺序存储呼叫,然后断言。

var calls = new List<string>(); //or an enum for different calls
FileEncrypter.When(x => x.Encrypt(stream, filename, encryptedFilename))
             .Do(x => calls.Add("encrypt"));
FileTransferProxy.When(x => x.SendUpload(encryptedFilename))
                 .Do(x => calls.Add("upload"));
// Act

// Assert calls contains "encrypt","upload" in the correct order

如果您最终尝试Received.InOrder,请在discussion group上留下一些反馈。如果我们得到一些关于它的反馈,那么我们就可以将它推广到核心命名空间。

答案 1 :(得分:0)

虽然它不是答案,但是作为单元测试的一部分验证显式顺序是不好的做法。您永远不应该测试实现细节。只需确保输入正确转换为输出并添加一些基本证明预期行为的替代方案。这就是为什么在RhinoMocks中不推荐使用这个功能的原因,而且FakeItEasy甚至不支持它。