简体   繁体   English

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

[英]How to mock ExceptionContext for testing using .NET Core 3 Web API and Moq

In order to properly test a custom ExceptionFilterAttribute in .NET Core 3 we need to mock an ExceptionContext in an Xunit test using Moq.为了在 .NET Core 3 中正确测试自定义 ExceptionFilterAttribute,我们需要使用 Moq 在 Xunit 测试中模拟 ExceptionContext。 How can I do this?我怎样才能做到这一点?

Exception Filter:异常过滤器:

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

I've looked everywhere and can't figure out a good way to mock these things in a way that ensures nothing throws an exception due to other missing dependencies.我到处寻找,但找不到一种好方法来模拟这些东西,以确保不会因其他缺少的依赖项而引发异常。 How can I mock ExceptionContext easily?如何轻松模拟ExceptionContext

The problem lies in the fact that if you are trying to mock ExceptionContext in order to return different exception types, you actually want to mock an exception and then use that mock exception when instantiating the ExceptionContext .问题在于,如果您试图模拟ExceptionContext以返回不同的异常类型,您实际上想要模拟一个异常,然后在实例化ExceptionContext时使用该模拟ExceptionContext

First, to instantiate the ExceptionContext for filters in a test you need to be able to instantiate the ActionContext .首先,要在测试中为过滤器实例化ExceptionContext ,您需要能够实例化ActionContext The ActionContext is not relevant to our test but is required by the dependency tree so we must instantiate it with as little customization as possible: ActionContext与我们的测试无关,但依赖树需要它,所以我们必须尽可能少的自定义实例化它:

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

After you are able to instantiate the ActionContext you can instantiate the ExceptionContext.在您能够实例化ActionContext您可以实例化 ExceptionContext。 Here we are also mocking the exception that is being used to build the ExceptionContext .在这里,我们还模拟了用于构建ExceptionContext This is the most important step as this is the value which changes the behavior we are testing.这是最重要的一步,因为这是改变我们正在测试的行为的值。

// 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
};

Doing it this way allows you to adequately test the behavior of an exception filter when given different exception types.这样做可以让您在给定不同的异常类型时充分测试异常过滤器的行为。

Full code:完整代码:

[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.");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM