簡體   English   中英

異常和測試 - 當我抓住它們時,如何對特定異常進行單元測試?

[英]Exceptions and testing - how to unit test something for specific exception when I catch them all?

我正在編寫MVC4 Web應用程序。 通常我嘗試在每個將ActionResult返回給用戶的控制器方法中放入“try {} catch {}”塊。 我這樣做是為了捕獲所有異常並顯示相應的消息,因此用戶永遠不會看到如下內容:

“引用未設置為對象的實例”

我的控制器通常看起來像這樣:

try
{

}
catch(MyFirstCustomException ex)
{
//set some message for the user and do some cleaning etc.

return ActionResult();
}
catch(MySecondCustomException ex) (and so on...)
{
//set some message for the user and do some cleaning etc.

return ActionResult();
}
catch(Exception ex)
{
//set some message for the user and do some cleaning etc.

return ActionResult();
}

但是現在我遇到了以下情況:我有AccountController和一個LogIn方法,我想寫一個單元測試(使用Microsoft單元測試框架),斷言那個沒有激活他的帳戶的用戶,將無法登錄。當檢測到這樣的嘗試時,我有一個名為UserNotActivatedException的特殊異常被拋出。 問題是 - 因為我在控制器中捕獲了所有異常,我的測試本身永遠不會看到這個異常 - 因此測試總是會失敗。 我設法通過為我的模型創建特殊狀態枚舉來繞過這個問題,如下所示:

public enum LoginViewModelStatus
{
NotLoggedIn = 0,
LoginSuccessfull = 1,
LoginFailed = 2,
UserNotActivatedException = 3,
UnknownErrorException = 100
}

並且當發生某事時將其設置為某個值(所以當我捕獲我的特殊UserNotActivatedException時 - 我將loginModelStatus設置為UserNotActivatedException ,依此類推)

我的問題:

  1. 有沒有更好的替代品呢?
  2. 我想在其他控制器中使用這個設計,這里有任何垮台嗎?
  3. 使用大量自定義異常來為用戶顯示消息是不是很好的設計,或者使用更多mini if(someCondition){return false;}測試會更好嗎?

您應該測試代碼在所有情況下返回預期結果,或多或少忽略方法如何工作。

即在您的情況下, Controller將多個異常轉換為不同的視圖 - 測試當您提供導致異常情況的數據時, Controller返回您期望的視圖。

如果控制器使用的較低級別的方法可能會拋出異常 - 也會測試它們,但這次是為了拋出特殊異常。

這取決於你有多少異常就足夠了。 良好的異常記錄可能比變化更重要。 在大多數情況下,您不應該向用戶顯示異常信息,而是“災難性錯誤。如果需要幫助,則會記錄ID為AB455的錯誤”。 應處理所有“預期異常”情況並將其作為正常流程呈現給用戶。

請注意,只要您擁有處理所有異常的代碼,就可以從操作中拋出異常。 HandleErrorAttribute這樣的Action過濾器可用於為特定操作/整個應用程序配置異常策略。

您可以將代碼包裝在try部件中,以便能夠對此部件進行單元測試。 這里,單元可測試部分簡單地“包裝”在MyUnitTestableMethod方法中:

try
{
    MyUnitTestableMethod();
}
catch(MyFirstCustomException ex)
{
    // ...
}
catch(MySecondCustomException ex) (and so on...)
{
    // ...
}
catch(Exception ex)
{
    // ...
}

吻:保持簡單(或保持簡單和愚蠢):)

看來你的代碼“太穩定了”。 也就是說,您的邏輯永遠不會產生錯誤。 從穩定性的角度來看這是好的,但不是很可測試的。

在這種情況下,我會有一個類來處理自定義邏輯捕獲從該類生成的所有異常,然后再返回ActionResult來分離邏輯。

class ActionClass
{
    public bool HandleLogin(...)
    {
        ...
    }
}

並使用這樣的類:

try
{
    ActionClass action = new ActionClass();
    action.HandleLogin(...)

}
// Catchblock here

這將允許您測試邏輯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM