2012-12-11 101 views
14

本來是想單元測試在下面的類的方法的方法單元測試,它返回一個空

public class DeviceAuthorisationService : IDeviceAuthorisationService 
{ 
    private DeviceDetailsDTO deviceDetailsDTO = null; 
    private IDeviceAuthorisationRepositiory deviceAuthorisationRepositiory; 

    public DeviceAuthorisationService(IDeviceAuthorisationRepositioryService paramDeviceAuthorisationRepository) 
    { 
     deviceAuthorisationRepositiory = paramDeviceAuthorisationRepository; 
    } 

    public void AuthoriseDeviceProfile(long paramUserID, string paramClientMakeModel) 
    { 
     if (deviceDetailsDTO == null) 
      GetCellPhoneDetails(userID); 

     if (deviceDetailsDTO.IsDeviceSelected == false) 
      throw new SomeCustomExceptionA(); 

     if (deviceDetailsDTO.CellPhoneMakeModel.ToLower() != paramClientMakeModel.ToLower()) 
      throw new SomeCustomExceptionB; 
    } 

    public void UpdateDeviceStatusToActive(long userID) 
    { 
     if (deviceDetailsDTO == null) 
      throw new InvalidOperationException("UnAuthorised Device Profile Found Exception"); 

     if (deviceDetailsDTO.PhoneStatus != (short)Status.Active.GetHashCode()) 
      deviceAuthorisationRepositiory.UpdatePhoneStatusToActive(deviceDetailsDTO.DeviceID); 
    } 

    private void GetCellPhoneDetails(long userID) 
    { 
     deviceDetailsDTO = deviceAuthorisationRepositiory.GetSelectedPhoneDetails(userID); 

     if (deviceDetailsDTO == null) 
      throw new SomeCustomException() 
    } 

} 

注:

  • 方法名稱= AuthoriseDeviceProfile返回void
  • 該方法檢查userSentMakeModel針對存儲在數據庫中的一個匹配
  • 如果匹配 - 它只是返回(即不會更改任何狀態)

我們將如何單元測試這種方法?

  • 曾經嘲笑回購
  • 已覆蓋的情況下「拋出異常」
  • 問題是所有方案中如何進行單元測試順利即用戶; S makeModel與倉庫相匹配; S makeModel

任何設計建議,使此可測試是最受歡迎 在此先感謝。

回答

14

由於你的方法返回void,所以它可能有一些你可以測試/斷言的副作用。

就你而言,一個選項將是提供IDeviceAuthorisationRepositioryService的模擬實例。然後您可以檢查是否發生了對UpdatePhoneStatusToActive的呼叫。下面是使用Moq一個解決方案:

var mock = new Mock<IDeviceAuthorisationRepositioryService>(); 

var service = new DeviceAuthorisationService(mock.Object); 
service.UpdateDeviceStatusToActive(....); 

mock.Verify(x => service.UpdatePhoneStatusToActive(), Times.Never()); 
+0

感謝alexn - 一直在使用莫q並發現它非常有幫助 –

7

如果一個方法是無效的,那麼它應該有一些可觀察的副作用 - 否則它是沒有意義的。因此,不是測試返回值,而是測試副作用。在這種情況下,它看起來像那些可能在哪些情況下拋出異常的東西。

(在這裏,「拋出一個異常」被認爲是一種副作用,你也可以把它作爲一個隱含的那種,當然返回值的...)

3

您可以在機上設定的預期異常試驗。在nUnit中,它看起來像這樣:

[Test] 
[ExpectedException(typeof(InvalidOperationException))] 
public void TestAuthoriseFail() 
{ 
    // do something that should make the tested method throw the exception 
} 
5

注入嘲笑的存儲庫。測試是否調用了存儲庫上的某些方法。

2

即使你的方法返回void,它必須做的事情是對你有用的(否則將有一個毫無意義的方法)。

從你的代碼,我猜有本質上的「有用」的東西2種口味的AuthoriseDeviceProfile方法做:

  • 呼籲基礎上,IDeviceAuthorisationRepositiory
  • 拋出各種異常的GetSelectedPhoneDetails方法一定條件下

因此進行單元測試的方法,你應該做的是對應於該兩件事情:

  • 注入模擬IDeviceAuthorisationRepositiory並將它記錄和/或斷言GetSelectedPhoneDetails是否叫
  • 運動試驗方法誘發各種異常,並捕獲他們,因爲他們被拋出來驗證:
    • 的例外是事實上拋出
    • 被拋出的異常是一個合適的每個場景
+0

謝謝Chamila_c。在單元測試中通過發送模擬庫來覆蓋「拋出異常」。我們如何涵蓋「一切順利的場景」 –

+0

設置測試場景以避免拋出異常,然後檢查是否沒有在「catch」子句中找到任何異常。這可以像設置布爾值一樣簡單,只需要將代碼切換到「catch」中即可。然後,如果在測試結束時布爾值保留其初始值,那麼您知道沒有例外拋出。 –

+0

Isnt試圖在被認爲是測試氣味的測試中嘗試捕獲嗎? –

相關問題