c# - 如何模拟 ExceptionContext 以使用 .NET Core 3 Web API 和 Moq 进行测试

标签 c# unit-testing .net-core moq xunit

为了在 .NET Core 3 中正确测试自定义 ExceptionFilterAttribute,我们需要使用 Moq 在 Xunit 测试中模拟 ExceptionContext。我怎样才能做到这一点?

异常过滤器:

public class CustomExceptionFilter : ExceptionFilterAttribute
{
  public override OnException(ExceptionContext context)
  {
    /* Code here that handles exceptions */
  }
}

我到处寻找,但找不到一种好方法来模拟这些东西,以确保不会因其他缺少的依赖项而引发异常。我该如何模拟 ExceptionContext容易地?

最佳答案

问题在于,如果您试图模拟 ExceptionContext为了返回不同的异常类型,您实际上想要模拟一个异常,然后在实例化 ExceptionContext 时使用该模拟异常。 .

首先,实例化ExceptionContext对于测试中的过滤器,您需要能够实例化 ActionContext . ActionContext与我们的测试无关,但依赖树需要它,所以我们必须尽可能少的定制实例化它:

var actionContext = new ActionContext()
{
  HttpContext = new DefaultHttpContext(),
  RouteData = new RouteData(),
  ActionDescriptor = new ActionDescriptor()
};

在您能够实例化 ActionContext 之后您可以实例化 ExceptionContext。在这里,我们还模拟了用于构建 ExceptionContext 的异常。 .这是最重要的一步,因为这是改变我们正在测试的行为的值。
// The stacktrace message and source member variables are virtual and so we can stub them here.
var mockException = new Mock<Exception>();

mockException.Setup(e => e.StackTrace)
  .Returns("Test stacktrace");
mockException.Setup(e => e.Message)
  .Returns("Test message");
mockException.Setup(e => e.Source)
  .Returns("Test source");

var exceptionContext = new ExceptionContext(actionContext, new List<FilterMetadata>())
{
  Exception = mockException.Object
};

这样做可以让您在给定不同的异常类型时充分测试异常过滤器的行为。

完整代码:
[Fact]
public void TestExceptionFilter()
{
  var actionContext = new ActionContext()
  {
    HttpContext = new DefaultHttpContext(),
    RouteData = new RouteData(),
    ActionDescriptor = new ActionDescriptor()
  };

  // The stacktrace message and source member variables are virtual and so we can stub them here.
  var mockException = new Mock<Exception>();

  mockException.Setup(e => e.StackTrace)
    .Returns("Test stacktrace");
  mockException.Setup(e => e.Message)
    .Returns("Test message");
  mockException.Setup(e => e.Source)
    .Returns("Test source");

  // the List<FilterMetadata> here doesn't have much relevance in the test but is required 
  // for instantiation. So we instantiate a new instance of it with no members to ensure
  // it does not effect the test.
  var exceptionContext = new ExceptionContext(actionContext, new List<FilterMetadata>())
  {
    Exception = mockException.Object
  };

  var filter = new CustomExceptionFilter();

  filter.OnException(exceptionContext);

  // Assumption here that your exception filter modifies status codes.
  // Just used as an example of how you can assert in this test.
  context.HttpContext.Response.StatusCode.Should().Be(500, 
    "Because the response code should match the exception thrown.");
}

关于c# - 如何模拟 ExceptionContext 以使用 .NET Core 3 Web API 和 Moq 进行测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59219328/

相关文章:

unit-testing - 如何对 FluentMigrator 迁移进行单元测试?

c# - 单元测试我认为如何指出正在测试的类上的逻辑错误

docker - 使用 dotnet-core 项目运行 docker 时未找到依赖项 list 中指定的程序集

c# - 无法构建 .Net core 2.2 项目?找不到类型或命名空间名称 'System'

c# - 路由属性不会生成漂亮的 URL

c# - 如何在 C# 中更改主机名?

c# - linq中varchar字段的和,如何进行转换

c# - 存储过程和 C# SqlDataReader 返回的行数少于预期

c# - 单元测试基于 umbraco 的网站

javascript - 将 JavaScript 对象传递给 Controller