2014-10-19 165 views
0

例如正確的工作,我有以下方法:有例外

 public void MeetingNoteSave(int MeetingID, string note, bool IsInviter, string Username) 
     { 
       meeting = Get<Meeting>(p => p.MeetingID == MeetingID && p.UserInviter.aspnet_User.UserName == Username); 
       MeetingNoteSaveCheckings(meeting, MeetingID); 
// some actions here 
     } 

     void MeetingNoteSaveCheckings(Meeting meeting, int MeetingID) 
     { 
      DateTime currentDateWithTime = DateTime.Now; 
      if (meeting == null) 
      { 
       throw new Exception("Meeting does not exist. MeetingID=" + MeetingID); 
      } 
      DateTime meetingTime = meeting.MeetingTime.Day.AddHours(meeting.MeetingTime.Hour).AddMinutes(meeting.MeetingTime.Minute); 
      if (meetingTime > currentDateWithTime) 
      { 
       throw new Exception("Meeting is future. MeetingID=" + MeetingID + ". Meeting time = '" + meetingTime + "', Current time='" + currentDateWithTime + "'"); 
      } 
     } 

因此,方法可以拋出兩種例外 - 會議不是在所有的這些參數或時相比,當前時間滿足更多的時間存在(當應該過去或現在)。

現在,我正在寫單元測試。簡單的方法:

[TestMethod] 
    public void MeetingNoteSave() 
    { 
     _repository.MeetingNoteSave(1, "My note", true, "[email protected]"); 
    } 

當然,呼叫單元測試會失敗,並帶有一些參數。我想抓住這些情況,所以,測試應該是成功的。我可以通過2種方式來完成。第一個是簡單的,但有點髒:

 try 
     { 
      _repository.MeetingNoteSave(1, "My note", true, "[email protected]"); 
     } 
     catch(Exception ex) 
     { 
      if (ex.Message.IndexOf("Meeting does not exist")>=0) 
      { 
       // some actions 
      } 

      if (ex.Message.IndexOf("Meeting is future")>=0) 
      { 
       // some actions 
      } 
     } 

所以,測試將是不正確的輸入參數(因此,單元測試可以用於測試方法與不正確的參數)的成功,但失敗,並遇到錯誤。好。

其他方式 - 創建特殊的虛擬例外像MeetingNullException和MeetingFutureException

public class MeetingNullException : Exception 
{ 
} 

public class MeetingFutureException : Exception 
{ 
} 

扔,把他們捉住。更正確,但更多的代碼。虛擬代碼。 哪種方式更準確?

回答

3

既不是,它們都是有缺陷的。你的第二種方法是朝着正確的方向:你應該避免拋出Exception類型的一般例外;特定的子類更富有表現力。

你有你的測試做的又是什麼用[ExpectedException]屬性,這將讓他們看起來像這樣:

[TestMethod] 
[ExpectedException(typeof(MeetingNullException))] 
public void MeetingNoteSave_WithNotExistingMeeting() 
{ 
    _repository.MeetingNoteSave(1, "My note", true, "[email protected]"); 
} 

[TestMethod] 
[ExpectedException(typeof(MeetingFutureException))] 
public void MeetingNoteSave_WithFutureDate() 
{ 
    _repository.MeetingNoteSave(1, "My note", true, "[email protected]"); 
} 

確保您只有一個測試程序的每一個可能的流程:2個例外意味着2個測試。我個人可能會避免創建特定的子類,只需使用ArgumentException,但這取決於您自己決定。如果您具有富有表現力的測試名稱並且代碼具有足夠的自我記錄功能,那麼無論如何您都會知道提及哪個參數。

+0

謝謝。另外,你可以用ArgumentException向我展示你的方法嗎? – 2014-10-19 09:48:30

+1

它和上面完全一樣,只有你使用'[ExpectedException(typeof(ArgumentException))]''並拋出新的ArgumentException(「meeting」);'。那麼什麼是導入,從方法的名稱中明確指出:'SaveMeetingNote_WithNullMeeting_ThrowsArgumentException'和參數:'_repository.SaveMeetingNote(VALID_ID,INVALID_NAME,VALID_ISINVITED,VALID_EMAIL);'這些是您在此之前定義的常量。那麼你的意思是沒有問題的。 – 2014-10-19 09:51:33