[英]Using MOQ to test a repository
我試圖使用MOQ測試存儲庫來模擬repo的行為。 我對MOQ不熟悉,所以請耐心等待。
給出以下方法:
public static SubmissionVersion DeleteNote(IRepository repository, SubmissionVersion version, Guid noteId)
{
Note note = repository.GetById<Note>(noteId);
version.Notes.Remove(note);
repository.Save(version);
repository.Delete(note);
return repository.GetById<SubmissionVersion>(version.Id);
}
這個測試看起來不錯嗎?
[Fact]
public void DeleteNoteV2()
{
// Arrange
var note = new Note{ Id = Guid.NewGuid()};
var subVersion = new Mock<SubmissionVersion>();
subVersion.Setup(x => x.Notes.Remove(note));
var repo = new Mock<IRepository>();
repo.Setup(x => x.GetById<Note>(note.Id)).Returns(note);
repo.Setup(x => x.GetById<SubmissionVersion>(It.IsAny<Guid?>())).Returns(subVersion.Object);
// Act
SubmissionVersion.DeleteNote(repo.Object, subVersion.Object, note.Id.Value);
// Assert
repo.Verify(x => x.GetById<Note>(note.Id), Times.Once());
repo.Verify(x => x.Save(subVersion.Object), Times.Once());
repo.Verify(x => x.Delete(note), Times.Once());
subVersion.Verify(x => x.Notes.Remove(It.IsAny<Note>()), Times.Once());
}
你的方法很好,但我會調整一些東西。 我對您的測試和模擬組件進行了一些更改,您可以在下面看到。
單元測試
您在單元測試中的測試方法(見下文)與您在問題中定義的方法並不完全匹配。
單元測試方法調用:
SubmissionVersion.DeleteNote(repo.Object, subVersion.Object, note.Id.Value);
測試方法:
public static SubmissionVersion DeleteNote
(IRepository repository, SubmissionVersion version, Guid noteId)
我假設上面的方法是另一個類的一部分,我稱之為NotesHelper - 不是存儲庫調用的理想名稱,但它只是為了讓編譯工作。
我個人會將你的單元測試分成兩個獨立的單元測試。 一個用於驗證是否調用了所需的方法,另一個用於驗證是否已從集合中刪除了注釋。
我還創建了一個fakeSubmissionVersion,而不是創建一個模擬的SubmissionVersion。 這是因為SubmissionVersion中的例程可能不是可模擬的。 您還可以進行基於狀態的測試(首選)以確保版本.Notes.Remove(注意); 被稱為。
[Fact]
public void DeleteNote_Deletion_VerifyExpectedMethodsInvokecOnlyOnce()
{
// Arrange
var note = new Note { Id = Guid.NewGuid() };
var fakeSubmissionVersion = new SubmissionVersion() { Notes = new List<Note>() };
var repo = new Mock<IRepository>();
repo.Setup(x => x.GetById<Note>(It.IsAny<Guid>())).Returns(note);
// Act
NotesHelper.DeleteNote(repo.Object, fakeSubmissionVersion, note.Id.Value);
// Assert
repo.Verify(x => x.GetById<Note>(note.Id), Times.Once());
repo.Verify(x => x.Save(fakeSubmissionVersion), Times.Once());
repo.Verify(x => x.Delete(note), Times.Once());
}
通過在自己的測試中定義每個驗證,可以進一步改進上述測試。
[Fact]
public void DeleteNote_Deletion_VerifyDeleteMethodCalledOnlyOnce()
這樣,如果一個測試失敗,我們就會確切地知道哪個方法沒有被期望調用。 有時,如上所述進行多次驗證可能會有問題。 例如,如果尚未調用Save方法,則永遠不會知道是否已調用Delete方法。 這是因為在未調用Save方法且測試執行已終止時拋出了異常。
這將導致多次測試,但它們更易讀和可維護。 當然,您可以將公共代碼重構為工廠或輔助方法。
[Fact]
public void DeleteNote_RemoveNotes_ReturnsExpectedNotes()
{
// Arrange
var note = new Note { Id = Guid.NewGuid() };
var fakeSubmissionVersion = new SubmissionVersion() { Notes = new List<Note>() { note } };
var repo = new Mock<IRepository>();
repo.Setup(x => x.GetById<Note>(It.IsAny<Guid>())).Returns(note);
// Act
NotesHelper.DeleteNote(repo.Object, fakeSubmissionVersion, note.Id.Value);
// Assert
Assert.AreEqual(0, fakeSubmissionVersion.Notes.Count);
}
附加說明:同時提供描述性單元測試方法名稱可提高單元測試的可讀性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.