捕获异常而不抛出类型

Catch exception without throwing type

我是 xUnit 的新手,我正在尝试增加我的测试覆盖率。我有一个 class 结构,如下所示:

public class Class1 
{
   public override void Method1() 
   {
      try 
      {
         // some code logic
      } 
      catch (CoreException ex)
      {
         BmpException lex = new BmpException();
         throw lex;
      }
      catch (CodedException ex)
      {
         BmpException lex = new BmpException();
         throw lex;
      }
   }
}

我的 xUnit 测试方法如下所示:

[Fact]
public void TestMethod()
{
   Class1 SomeClass = new Class1();

   // Works but doesn't affect code coverage ?
   Assert.Throws<BmpException>(() => SomeClass.Method1());

   // Test failed - Expected: CodedException Actual: BmpException
   // Assert.Throws<CodedException>(() => SomeClass.Method1());

   // Test failed - Expected: CoreException Actual: BmpException
   // Assert.Throws<CoreException>(() => SomeClass.Method1());
}

所以我在这里面临的问题是我需要涵盖 CoreException 和 CodedException 块的测试。由于 Assert.Throws<> 捕获表达式并断言类型,我无法找到解决方法来完成我的测试覆盖。

如有任何帮助,我们将不胜感激。谢谢,

你可以像这样得到抛出的异常:

 var ex = Assert.Throws<BmpException>(() => SomeClass.Method1());

 Assert.Equal("test message", ex.Message);

假设BmpException继承自System.Exceptionclass。要保留原始异常,您应该在自定义异常 BmpException lex = new BmpException(ex); 中传递原始异常,这将在 InnerException 中保留堆栈跟踪。这是包装异常以添加附加信息并保留原始异常的标准方法。这样您就可以对 InnerException 进行断言。

Assert.Equal(typeof(CoreException), ex.InnerException.GetType());
//Add as many assertion as you like here.

I have a class structure that looks like so:

简单地抛出一个不同的异常通常是非常糟糕的做法,因为您会丢失所有相关信息。 至少你应该wrap the exception.

因为您没有包含所有相关代码

// some code logic

不可能给你程序化的答案。基于缺乏信息,唯一可以给出的真正答案是您的测试需要导致 一些代码逻辑 抛出每种类型的异常(CoreExceptionCodedException) 以增加代码覆盖率。

// Test failed - Expected: CodedException Actual: BmpException

// Assert.Throws(() => SomeClass.Method1());

您永远不能将类型断言为 CoreExceptionCodedException,因为它们是 Swallowed or Error Hiding。这些异常会一直丢失在方法调用中。

Since Assert.Throws<> catches the expression AND asserts the type, I am unable to find a workaround

您必须捕获抛出的类型:

var ex = Assert.Throws<BmpException>(() => SomeClass.Method1());

你不关心为什么它真的是那种类型的异常,只要你能提供一种方法让逻辑通过特定的逻辑编程路由抛出那种类型。

例如:

public void AnyBodyWantAPeanut(int i)
{
  try 
  {
    if (i == 1) 
      throw new InvalidOperationException("You keep using that word");
    if (i == 2) 
      throw new ArgumentException("I don't think it means");
    throw new ArithmeticException ("What you think it means");
  }
  catch (Exception ex)
  {
    Throw Exception("No more rhymes now I mean it!");
  }
}

这具有 3 的圈复杂度,因为存在三种可能的路线,即使只有一种结果。要使此代码具有 100% 的代码覆盖率,必须通过确保逻辑支持结果来测试以下测试:

public class Class1_Tests
{
  public AnyBodyWantAPeanut_WithValue1_ReturnsException
  {
    //Assign
    var a = new Class1();
    //Act
    var method = () => a.AnyBodyWantAPeanut(1);
    //Assert
    Assert.Throws<Exception>(method);
  }
  
  public AnyBodyWantAPeanut_WithValue2_ReturnsException
  {
    //Assign
    var a = new Class1();
    //Act
    var method = () => a.AnyBodyWantAPeanut(2);
    //Assert
    Assert.Throws<Exception>(method);
  }

  public AnyBodyWantAPeanut_WithValue1_ReturnsException
  {
    //Assign
    var a = new Class1();
    //Act
    var method = () => a.AnyBodyWantAPeanut(0);
    //Assert
    Assert.Throws<Exception>(method);
  }
}