2010-08-13 66 views
0

(C#,Rhino Mocks,MbUnit)。單元測試沒有可觀察狀態變化的方法

我有一個名爲AccountManager的類,它有一個RegisterUser()方法。此方法返回void,但會爲任何錯誤拋出異常。 AccountManager調用調用其AddUser()方法的IDataRepository來執行數據庫插入。

我使用Rhino Mock模擬了IDataRepository,並拋出了一個給定的參數集,並模擬了存儲庫中引發的異常。

[Test] 
    public void RegisterKnownUser() 
    { 
     MockRepository mocks = new MockRepository(); 
     IDataRepository dataRepository = mocks.StrictMock<IDataRepository>(); 

     using (mocks.Record()) 
     { 
      Expect.Call(() => dataRepository.AddUser("abc", "abc", "[email protected]", "a", "bc")).Throw(
       new InvalidOperationException()); 
     } 

     using (mocks.Playback()) 
     { 
      AccountManager manager = new AccountManager(dataRepository); 
      Assert.Throws(typeof (InvalidOperationException),() => manager.RegisterUser("abc", "abc", "[email protected]", "a", "bc")); 
     } 
    } 

此測試正常工作。

我的問題是如何處理提供給RegisterUser的參數是正確和有效的情況。真正的IDataRepository不會返回任何東西,也不會拋出任何異常。所以總之AccountManager的狀態不會改變。這是否意味着我不需要測試AccountManager.RegisterUser,因爲它會導致我無法直接在被測試的類和方法中觀察到。在模擬中對狀態進行測試對我來說有點味道。我認爲,只要我單獨測試IDataRepository.AddUser,那麼我就不需要測試AccountManager.RegisterUser的輸入,這些輸入會導致類中沒有任何可觀察的內容。

在此先感謝。

+0

Ribgy:你能提供你想要描述的測試用例的代碼嗎? AccountManager會調用dataRepository嗎? – 2010-08-13 09:56:41

回答

2

如果AccountManager調用DataPrepository,那麼您的測試用例仍然會驗證某些內容。此處的錄製/播放會驗證是否進行了通話。如果調用不成功,測試用例將失敗。如果它做了兩次/錯誤的參數,它會失敗。

這可能是一個非常基本的測試用例,但它仍然是一個很好的測試用例,並且不要求您將狀態置於模擬對象中。

+0

謝謝(還有主馬)。我已經走下了測試的路線,不會拋出異常,以獲得良好的數據。 – 2010-08-13 10:32:23

0

您可能需要使用有效參數測試該方法,以確保它不會拋出任何異常。換句話說,你不能觀察狀態改變或使用返回值(因爲它是無效的),但你可以觀察到該方法沒有例外地運行。

順便說一句,如果方法不返回值,也不改變AccountManager狀態,它確實改變一些東西,否則(如果沒有,比你應該從你的代碼中刪除這確實什麼都沒有的方法) 。
例如,它可能會影響DataRepository。或者在數據庫中添加一條記錄。在這種情況下,您至少可以測試數據是否更改或記錄是否成功添加。或者它可能會記錄一個事件,說明新用戶已註冊,因此您可以在測試中檢查日誌事件是否在此處。

我想只要我考IDataRepository.AddUser seperately那麼我不應該需要測試AccountManager.RegisterUser因爲這將導致沒有觀察到在課堂上的投入

如果AccountManager.RegisterUser沒有增加IDataRepository.AddUser除參數強制執行外,如果您已經測試IDataRepository.AddUser,則不需要測試它。如果它檢查參數,則調用AddUser並執行其他操作,那麼檢查它是否正確將是一件好事。

比方說,你有:

public void AddUser(string userName, string userMail, string passwordHash) 
{ 
    // [...] Add a user to the database. 
} 

public void RegisterUser(string userName, string userMail, string passwordHash) 
{ 
    if (string.IsNullOrEmpty(userName)) throw new ArgumentNullException(...); 
    if (string.IsNullOrEmpty(userMail)) throw new ArgumentNullException(...); 
    if (string.IsNullOrEmpty(passwordHash)) throw new ArgumentNullException(...); 
    if (!Checks.IsValidMail(userMail)) throw new ArgumentException(...); 

    this.AddUser(userName, userMail, passwordHash); 

    this.SaveToLog(LogEvent.UserRegistered, userName, this.IPAddress); 
} 

RegisterUser,你通過傳遞錯誤的參數和預期異常測試前四行。第五行不能測試,因爲你已經測試過AddUser。最後,必須測試第六行以確保當您使用有效參數調用RegisterUser時,會創建日誌條目。