2012-07-12 81 views
0

我有一個save()方法,不太確定如何測試。下面是我的代碼。moq,如何測試保存方法?

public interface IRepository<T> 
{ 
    T Get(int id); 
    void Save(T item); 
    void Delete(int id); 
} 

save方法不返回任何值,我無法比較該值。然而,我已經有4個用戶,添加另一個後,我只檢查用戶總數,是否足以測試它?

[Test] 
public void Add_a_new_smoothie_user_should_return_total_5_users() 
{ 
    // Arrange 

    var totalUsers = _users.Count(); 

    _mockUserRepository.Setup(s => s.Save(It.IsAny<User>())) 
     .Callback((User user) => _users.Add(user)); 

    var newUser = new User 
         { 
          Id = 3, 
          Email = "[email protected]", 
          Password = "1234567".Hash(), 
          Firstname = "", 
          Lastname = "", 

          CreatedDate = DateTime.Now, 
          LastLogin = DateTime.Now, 

          AccountType = AccountType.Smoothie, 
          DisplayName = "", 
          Avatar = "", 
          ThirdPartyId = "", 
          Status = Status.Approved, 
          Ip = "127.0.0.1" 
         }; 

    // Act 

    _mockUserRepository.Object.Save(newUser); 

    // Assert 

    Assert.AreEqual(5, _users.Count()); 
    Assert.AreEqual(1, _users.Count() - totalUsers); 
} 
+0

你能概述一下你的'保存'方法嗎?你有「代碼覆蓋率」嗎?我不認爲將'x'用戶添加到您的模擬將有效驗證該方法。您應該專注於測試所有流程(主要,替代,例外等),以便代碼覆蓋率相當高。 – Channs 2012-07-12 19:56:51

+0

我不太明白你的moq版本庫保存方法來執行你的委託。你在這裏測試什麼?您能否提供在此測試中執行的測試代碼? – Rafal 2012-07-12 19:57:07

+0

我的「保存」方法只是將新用戶保存到數據庫。我還沒有代碼,只是界面。我認爲你必須在編寫具體方法之前先寫單元測試。 – qinking126 2012-07-12 20:06:42

回答

3

您正在嘲笑您嘗試測試的功能部分。除了您持有用戶的數據類型的Add()方法之外,這些測試將不會被證實。最後,如果您的存儲庫正在工作,它不會提供任何意見。

您應該嘗試執行Database Sandbox以測試您的存儲庫功能。

+0

我正在使用存儲庫模式。現在,我只有界面,沒有具體的實現。我認爲這就是你如何進行單元測試,先寫測試,然後基於測試,寫出具體的方法。你可以給我一個例子如何測試保存方法。我的保存方法只是將新用戶保存到數據庫。 – qinking126 2012-07-12 20:05:03

+0

「實現了用於測試存儲庫功能的數據庫沙箱。」我不認爲這是單元測試。 – qinking126 2012-07-12 20:09:45

+0

您存儲庫存在,因此您不必擔心其他類中的數據庫操作。您可以在需要時模擬它,並像在測試中進行數據庫操作一樣。最後,單元測試與否,您還必須確保您的存儲庫工作。我認爲那是你想要完成的事情。 – 2012-07-12 20:16:37

0

您的存儲庫在哪裏存儲?如果它保存在某個文件中,那麼你可以將你的文件與一些模型文件(黃金)進行比較,其中一切都是手動檢查的,並且沒問題。如果是某個數據庫,則應該模擬數據庫接口,記錄所有插入查詢,然後將日誌與理想日誌進行比較。

1

不要爲模擬代碼編寫測試,因爲那些測試實際上不測試任何東西(當然,除了嘲笑框架實現)。

如何使用測試優先方法創建接口?這很容易。考慮你有一些FooController,這需要一些數據。在某些時候(在爲控制器編寫測試的過程中),您決定會有一些依賴關係,它會將這些數據提供給控制器(yep,repository)。您當前的控制器測試需要某些功能才能從數據存儲中獲取一些Bar對象。所以,你寫測試

Mock<IBarRepository> repositoryMock = new Mock<IBarRepository>(); 
repositoryMock.Setup(r => r.GetById(It.IsAny<int>()).Returns(new Bar()); 
FooController controller = new FooController(repositoryMock.Object); 
controller.Exercise(); 

此測試將無法編譯,因爲在這一點上你沒有IBarRepository接口,它是由控制器所需。你創建這個接口。而且您還可以將方法GetById添加到此界面。之後你執行控制器。

好消息 - 當控制器完成時,您將有IBarRepository接口定義,它具有API非常方便的控制器。

下一步是創建IBarRepository實現。我很少爲存儲庫編寫測試。但是,你能做到幾個方面:

  • 如果您有數據訪問代碼,這是使用存儲庫(ORM框架,ADO.NET類等),你可以嘲笑這些依賴關係,並確認您的倉庫實現對基礎數據訪問代碼進行所有必需的調用。這些測試非常脆弱。並且不要給您太多好處,因爲很少存儲庫包含複雜的業務邏輯。
  • 您可以使用真實的數據庫(例如內存中的SQLite)進行集成測試,並驗證數據庫表中是否真的存在CRUD。這些測試也很脆弱,非常耗時。但在這種情況下,您可以確定,該存儲庫按其應有的方式工作。