2013-05-13 106 views
0

當我運行此測試時,出現「Assert.Fail failed。Assert.AreEqual failed。Expected :. Actual :.」如何更改Assert.Fail消息

如何在錯誤消息結束時通過或未通過「實際:」的測試失敗?我使用「Assert.Fail(ex.Message);」在其他幾個測試中,所以我不能直接更改消息。

[TestMethod] 
    public void TestCreateUser() 
    { 
     try 
     { 
      AsaMembershipProvider prov = this.GetMembershipProvider(); 
      //call get user 
      MembershipCreateStatus status; 
      MembershipUser user = prov.CreateUser("testUserX", "12345", "[email protected]", "", "", true, null, out status); 

      Assert.AreNotEqual(status, MembershipCreateStatus.Success); 
      var isAuthenticated = prov.ValidateUser(user.UserName, "12345"); 

      Assert.IsTrue(isAuthenticated); 
      Assert.AreEqual(user.UserName, "testUserX"); 
      Assert.AreEqual(user.Email, "[email protected]"); 
      Assert.IsTrue(user.CreationDate==DateTime.Now); 
      //TODO Asserts 

     } 

     catch (Exception ex) 
     { 
      LogMessage(ex); 
      Assert.Fail(ex.Message); 
     } 
    } 
+1

你剛纔問這個嗎?其他斷言是否通過?如果你看到'Assert.Fail(ex.Message)'的值;''你將會看到'Actual'和'Expected',因爲你在斷言中傳遞了'ex.Message'屬性。 – Brian 2013-05-13 18:18:45

回答

2

附加信息添加:單元測試(一般來說)只能檢查單個組件。對於這個測試,我會刪除調用來驗證用戶,因爲它應該是它自己的檢查它自己的測試方法。

這意味着兩種試驗方法 CreateUser_IsSuccessful_IfCreatingUserThatDoesNotExist() ValidateUser_Authenticates_IfGivenCorrectUsernameAndPassword()

這是更具描述性的,則TestCreateUser方法名,並允許你做更細緻的檢測。接下來的測試可以是CreateUser_Fails_IfRecreatingExistingUser()

很難給出真正的好建議,因爲我們不知道您正在進行的項目的要求。如果你必須有定製的輸出,那麼我原來建議的將會起作用(但這不是一個最佳做法,這對我來說有點像黑客)。更好的解決方案是更多的東西是這樣的:

[TestMethod] 
public void TestCreateUser() 
{ 
    AsaMembershipProvider prov = this.GetMembershipProvider(); 
    //call get user 
    MembershipCreateStatus status; 
    MembershipUser user = prov.CreateUser("testUserX", "12345", "[email protected]", "", "", true, null, out status); 

    //Assert.AreNotEqual(status, MembershipCreateStatus.Success); 
    if (status != MembershipCreateStatus.Success) 
     Assert.Fail("Error message you want goes here for this case."); 
    var isAuthenticated = prov.ValidateUser(user.UserName, "12345"); 
    //Assert.IsTrue(isAuthenticated); 
    if (!isAuthenticated) 
     Assert.Fail("Error message you want goes here for this case."); 
    //Assert.AreEqual(user.UserName, "testUserX"); 
    if (user.UserName != "testUserX") 
     Assert.Fail("Error message you want goes here for this case."); 
    //Assert.AreEqual(user.Email, "[email protected]"); 
    if (user.Email != "[email protected]") 
     Assert.Fail("Error message you want goes here for this case."); 
    //Assert.IsTrue(user.CreationDate==DateTime.Now); 
    if (user.CreationDate != DateTime.Now) 
     Assert.Fail("Error message you want goes here for this case."); 
} 

其定製的錯誤信息和刪除笨重的嘗試捕捉這是沒有必要的。

由於答案被接受,我將離開原來的輸出結果,但我同意不應該以這種方式使用try catch(因此上述修正)。我使用的嘗試捕捉在測試的唯一情況是如果我專門測試該異常的特定類型提出了一個方案,如果違反業務規則

try 
{ 
    methodToThrowException(); 
    Assert.Fail("BusinessSpecificException was not thrown by the code."); 
} 
catch (BusinessSpecificException ex) 
{ 
    //Asserts go here 
} 

如果你想要的是將提高漏斗所有的斷言通過對catch塊,你要自定義的錯誤輸出它可以這樣實現:

[TestMethod] 
    public void TestCreateUser() 
    { 
     try 
     { 
      AsaMembershipProvider prov = this.GetMembershipProvider(); 
      //call get user 
      MembershipCreateStatus status; 
      MembershipUser user = prov.CreateUser("testUserX", "12345", "[email protected]", "", "", true, null, out status); 

      //Assert.AreNotEqual(status, MembershipCreateStatus.Success); 
      if (status != MembershipCreateStatus.Success) 
       throw new Exception("Error message you want goes here for this case."); 
      var isAuthenticated = prov.ValidateUser(user.UserName, "12345"); 

      //Assert.IsTrue(isAuthenticated); 
      if (!isAuthenticated) 
       throw new Exception("Error message you want goes here for this case."); 
      //Assert.AreEqual(user.UserName, "testUserX"); 
      if (user.UserName != "testUserX") 
       throw new Exception("Error message you want goes here for this case."); 
      //Assert.AreEqual(user.Email, "[email protected]"); 
      if (user.Email != "[email protected]") 
       throw new Exception("Error message you want goes here for this case."); 
      //Assert.IsTrue(user.CreationDate==DateTime.Now); 
      if (user.CreationDate != DateTime.Now) 
       throw new Exception("Error message you want goes here for this case."); 
      //TODO Asserts 

     } 

和測試方法仍然會運行Assert.Fail部分。幕後的Assert方法在內部做着與此非常類似的事情(儘管可能拋出派生的Exception類型而不是基類)。

作爲高層次的建議,我會說單元測試提供者將會非常困難。我在過去創建了一個自定義的,這是一個噩夢,重寫它的方式,讓我來控制我的輸入和輸出。我所要做的就是提供一個構造函數,它允許我爲外部依賴項傳遞接口以允許我編寫測試。當我這樣做,然後我能寫的測試,如

ReturnsCreatedUser_IfCreationIsSuccessful()ReturnsInvalidPassword_IfPasswordIsInvalid()

其中斷言看起來是這樣的:Assert.AreEqual(MembershipCreateStatus.Success, _status); Assert.IsNotNull(response);

Assert.AreEqual(MembershipCreateStatus.InvalidPassword, _status);

這是您嘗試測試提供程序時遇到的第二個問題。現在,用你想要的信息拋出異常將允許你完全自定義你的信息。

+2

實際的代碼應該拋出異常(應該由tets檢查),而不是測試。測試應該驗證行爲。雖然這種方法可以幫助改變異常信息,但根本不應該有任何try/catch。單元測試的觀點完全錯誤 – 2013-05-13 20:23:06

+0

我並不反對你。本着stackoverflow的精神,我不確定我是否應該直接刪除答案,或者在答案時回答。我會編輯我的答案以提供更好的指導,因爲它一直困擾着我。感謝您的建設性意見。 – 2013-05-14 13:26:12

+0

@ taras.roshko我根據您的反饋編輯了我的答案。希望它比以前更好。 – 2013-05-14 13:53:12

4

那麼,據我所知,你想爲你的斷言指定自定義失敗消息?

OK,

Assert.AreEqual(object expected, object actual, string message); 

here

,你甚至可以創建一些特殊的失敗斷言,讀到這裏大約CustomAsserts

IMO,你並不需要一個try-catch塊,只需添加自定義消息到您的斷言

1

「實際」來自ex.Message。 This is read-only

你可以做一些字符串操作雖然是這樣的:

catch (Exception ex) 
{ 
    string message = ex.Message.Substring(0, ex.Message.IndexOf("Actual:")); 
    LogMessage(message); 
    Asset.Fail(ex.Message); 
}