2013-04-18 42 views
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); 
} 

回答

3

嘗試Received.InOrderNSubstitute.Experimental命名空間。

像這樣的東西(我沒有測試過這一點):

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

謝謝大衛。我忘記了When-Do構造,這正是我所需要的。 NSubstitute.Experimental命名空間在NuGet包中不可用,我將如何獲得包含該命名空間的NSubstitute版本? –

+0

NuGet版本有它(它不是一個單獨的DLL,只是使用'使用NSubstitute.Experimental')。它是在v1.5.0中引入的(當前版本是v1.6.0)。 –

+1

我嘗試在最初使用聲明中放入,並且由於某些原因未能識別。它正在工作。我在討論組留下了一些反饋意見。謝謝! –

-1

雖然它不是一個答案persee,但驗證明確的順序作爲單元測試的一部分是不好的做法。你不應該測試實現細節。只要確保輸入正確轉換爲輸出並添加一些基本證明預期行爲的備選方案。這就是爲什麼這個功能在RhinoMocks中被棄用的確切原因,並且FakeItEasy甚至不支持它。

+0

FakeItEasy支持命令斷言:https://github.com/FakeItEasy/FakeItEasy/wiki/Ordered-assertions。我同意儘可能避免它,但在某些情況下它可能會有用。 –

+0

本書的實用單元測試包括時間(事情發生的順序),因爲它是一個完全有效的規範說,例如「在調用保存之前需要調用某個驗證程序」。或者在這種情況下,「在加載之前需要調用加密器。」。那麼如何確保這種規範在調用void方法的方法上依賴? –