2014-09-03 36 views
2

考慮以下的單元測試:什麼時候應該斷言SUT的行爲?

[Test] 
public void Success() 
{ 
    var userID = 5; 
    var user = new User(); 
    var dataAccess = new Mock<IDataAccess>(); 
    dataAccess.Setup(x => x.GetUser(userID)).Returns(user).Verifiable(); 
    var sut = new UserController(dataAccess.Object); 

    var returnedUser = sut.GetUser(userID); 

    Assert.AreSame(user, returnedUser); 
    dataAccess.Verify(x => x.GetUser(userID), Times.Once()); 
} 

最近讀數已建議我應該只使用模擬,以提供用戶和應該有一個單一的斷言(所述AreSame之一)。顯然理想的單元測試不應該擔心驗證sut的行爲。

更多類似這樣的:

[Test] 
public void Success() 
{ 
    var userID = 5; 
    var user = new User(); 
    var dataAccess = new Mock<IDataAccess>(); 
    dataAccess.Setup(x => x.GetUser(userID)).Returns(user); 
    var sut = new UserController(dataAccess.Object); 

    var returnedUser = sut.GetUser(userID); 

    Assert.AreSame(user, returnedUser); 
} 

這是簡化的測試更好?單元測試應該斷言它們所調用的方法的行爲還是僅僅是結果?

+1

可能重複的[狀態/相互作用的測試和混亂上混合(或濫用)他們](http://stackoverflow.com/questions/1300221/state-interaction-testing-and - 混淆 - 混合 - 或 - 濫用 - 他們) – 2014-09-03 09:13:02

+1

這是一個很好的背景文章閱讀:http://martinfowler.com/articles/mocksArentStubs.html – 2014-09-03 09:15:03

回答

2

一個基本思想是只有一個斷言在測試。所以也許你應該在這裏考慮兩個測試。第一個基於價值的測試很重要。第二次互動測試可能不適合這種情況。根據Roy Osherove的說法:'在調用另一個對象時使用交互測試是特定工作單元的最終結果。'

實施例:

namespace Tests 
{ 
    [TestClass] 
    public class UserControllerTest 
    { 
     [TestMethod] 
     public void GetUser_WhenCalled_ReturnsUserSameAsDataAccess() 
     { 
      // Arrange 
      const int userID = 5; 
      User expectedUser = new User(); 

      Mock<IDataAccess> dataAccessStub = new Mock<IDataAccess>(); 
      dataAccessStub.Setup(x => x.GetUser(userID)).Returns(expectedUser); 
      UserController controller = new UserController(dataAccessStub.Object); 

      // Act 
      User actualUser = controller.GetUser(userID); 

      // Assert 
      Assert.AreSame(expectedUser, actualUser); 
     } 

     [TestMethod] 
     public void GetUser_WhenCalled_GetUserOnDataAccessIsCalledOnce() 
     { 
      // Arrange 
      const int userID = 5; 
      const int getUserCallsCountExpected = 1; 
      int getUserCallsCount = 0; 

      Mock<IDataAccess> dataAccessMock = new Mock<IDataAccess>(); 
      dataAccessMock.Setup(x => x.GetUser(userID)).Callback(() => getUserCallsCount++); 
      UserController controller = new UserController(dataAccessMock.Object); 

      // Act 
      controller.GetUser(userID); 

      // Assert 
      Assert.AreEqual(getUserCallsCountExpected, getUserCallsCount); 
     } 
    } 
} 
+0

我同意第一次測試。但我總是很難理解第二個測試增加什麼價值?它不是在測試API的內部實現嗎?這個測試對重構有彈性嗎?只要公衆行爲沒有改變,單位測試是否應該繼續通過? – Amol 2014-09-04 04:44:23

+0

@Amol是的,我認爲你是對的,第二個測試可能不適合在這種情況下。我編輯了答案。 – dee 2014-09-04 06:48:47

相關問題