簡體   English   中英

"內部異常的單元測試"

[英]Unit testing for inner exceptions

我正在使用 Visual Studio 的集成框架編寫一些單元測試。 我需要編寫一些在引發適當異常時通過的測試用例。 問題是我需要測試的異常是嵌套在更一般的異常中的內部異常。 是否有一些簡單的解決方案或者我需要擴展整個功能。 我目前正在使用 [ExpectedException] 屬性,但在這種情況下它不會有什么好處。

我也很好奇當我們使用 [ExpectedException] 時會發生什么,而我們在測試本身也有一些 Assert 邏輯。 是否評估了條件(拋出了異常並且 Assert 語句被證明是有效的)或者在拋出正確的異常后立即通過了測試?

不是一個完整的解決方案,但在 NUnit 中,你可以做這樣的事情:

 var ex = Assert.Throws<Exception>(() => thing.ThatThrows());
 Assert.That(ex.InnerException, Is.TypeOf<BadException>() );

也許你可以在你的測試框架中?

如果您的框架不支持自定義拋出,您通常有兩種選擇:

  1. 自己實現
  2. 更改(或擴展)框架

我將從第二個解決方案開始。 考慮使用FluentAssertions庫。 它允許你做這樣的事情:

Action deleteUser = () => usersRepository.Delete(new User { Id = null });

deleteUser
    .ShouldThrow<UserNotFoundException>()
    .WithInnerException<ArgumentNullException>()
    .WithInnerMessage("User Id must have value");

您仍將使用 Visual Studio 測試框架,只是您將擁有一個用於流暢斷言的額外庫。

另一方面,首選需要更多的工作,因為手動解決方案通常是這種情況:

try
{
    usersRepository.Delete(new User { Id = null });
    Assert.Fail("Deleting user with null id should throw");
}
catch (UserNotFoundException ue)
{
    Assert.AreEqual(ue.InnerException.Message, "User Id must have value");
}

您將ExpectedException屬性替換為聲明實際異常實例的自定義代碼。 就像我說的,這是更多的工作,但確實有效。

這是一個老問題,但我想與你們分享我自己的ExpectedInnerExceptionAttribute實現。 也許對某人有用

public class ExpectedInnerExceptionAttribute : ExpectedExceptionBaseAttribute
 {
   public ExpectedInnerExceptionAttribute(Type exceptionType)
   {
     this.ExceptionType = exceptionType;
   }

   public Type ExceptionType { get; private set; }

   protected override void Verify(Exception ex)
   {
     if (ex != null && ex.InnerException != null
           && ex.InnerException.GetType() == this.ExceptionType)
      {
         return;
      }

       throw ex;
    }
}

您還可以擴展它以檢查異常消息等。您只需要在驗證方法中添加您自己的邏輯即可。

對於單元測試,我目前使用FluentAssertions 自從我學會了它,我再也不想以任何其他方式斷言東西。

對於斷言異常,請查看文檔的這一部分

特別是這部分

Action act = () => subject.Foo2("Hello");

act.ShouldThrow<InvalidOperationException>()
     .WithInnerException<ArgumentException>()
     .WithInnerMessage("whatever")

FluentAssertions<\/a>真的很有幫助。

我使用它實現了我的解決方案,如下所示。 這是從AggregateException<\/code>檢查我的自定義異常ProcessFailureException<\/code>

Func<Task> func = async () => await item.ProcessAsync(context, message);
func.Should().Throw<AggregateException>().WithInnerException<ProcessFailureException>();

只需使用GetAwaiter()GetResult()來檢查內部異常:

Assert.Throws<InnerException>(() => thing.GetAwaiter().GetResult());

例如

Assert.Throws<CommunicationException>(() => thing.GetAwaiter().GetResult());

暫無
暫無

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

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