如何在ASP.NET Web Api中对Action Filter进行单元测试?

Aar*_*her 52 .net unit-testing action-filter asp.net-web-api

我想在我的服务中添加一个Action Filter来处理向响应消息添加链接数据.我发现我需要模拟HttpActionExecutedContext,但这是一个很难模拟的类,你如何处理Action Filter测试?

tug*_*erk 58

你可以创建一个假的HttpActionExecutedContext,如下所示:

public static HttpActionContext CreateActionContext(HttpControllerContext controllerContext = null, HttpActionDescriptor actionDescriptor = null)
{
    HttpControllerContext context = controllerContext ?? ContextUtil.CreateControllerContext();
    HttpActionDescriptor descriptor = actionDescriptor ?? new Mock<HttpActionDescriptor>() { CallBase = true }.Object;
    return new HttpActionContext(context, descriptor);
}

public static HttpActionExecutedContext GetActionExecutedContext(HttpRequestMessage request, HttpResponseMessage response)
{
    HttpActionContext actionContext = CreateActionContext();
    actionContext.ControllerContext.Request = request;
    HttpActionExecutedContext actionExecutedContext = new HttpActionExecutedContext(actionContext, null) { Response = response };
    return actionExecutedContext;
}
Run Code Online (Sandbox Code Playgroud)

我只是从ASP.NET Web API源代码中复制并粘贴了该代码:ContextUtil类.以下是他们如何测试一些内置过滤器的几个示例:

ActionFilterAttributeTestActionFilterAttribute一个抽象类的测试类,但你会得到这个想法.

  • 进一步的读者:请注意,自2012年以来,API已经发生了一些变化.最新的ContextUtil类可以在这里找到:https://aspnetwebstack.codeplex.com/SourceControl/latest#test/System.Web.Http.Test/Util/ ContextUtil.cs (5认同)

Sam*_*les 25

只是新的一个.

private HttpActionContext CreateExecutingContext()
{
    return new HttpActionContext { ControllerContext = new HttpControllerContext {   Request = new HttpRequestMessage() } };
}

private HttpActionExecutedContext CreateExecutedContextWithStatusCode(HttpStatusCode statusCode)
{
    return new HttpActionExecutedContext
    {
        ActionContext = new HttpActionContext
        {
            ControllerContext = new HttpControllerContext
            {
                Request = new HttpRequestMessage()
            }
        },
        Response = new HttpResponseMessage
        {
            StatusCode = statusCode,
            Content = new StringContent("blah")
        }
    };
}
Run Code Online (Sandbox Code Playgroud)


小智 11

尝试测试我构建的自定义未处理的异常过滤器时遇到了同样的问题.

这样做了.大量的新功能和很长的代码.

var httpActionExecutedContext = new HttpActionExecutedContext(
    new HttpActionContext(
        new HttpControllerContext(
            new HttpConfiguration(),
            Substitute.For<IHttpRouteData>(),
            new HttpRequestMessage()),
    Substitute.For<HttpActionDescriptor>()),
    null);
Run Code Online (Sandbox Code Playgroud)

使用了NSubstiute,但是您选择的任何处理抽象基类的模拟框架都可以.

希望这可以帮助


小智 6

我也一直在撞墙上撞墙.我尝试了contextUtil,但一直得到一个空引用异常.我发现了如何在这篇文章中调用actionFilter NB当使用过滤器的Mock实例时没有调用actionFilter,我不得不使用真实对象.HTH

特别:

var httpActionContext = new HttpActionContext
{
    ControllerContext = new HttpControllerContext
    {
        Request = requestMessage
    }
};

//call filter
var filter = new FooFilter();
filter.OnActionExecuting(httpActionContext);
Run Code Online (Sandbox Code Playgroud)


3DP*_*ner 5

参考/sf/answers/3111314461/

您可以使用以下内容自己创建 HTTPActionContext:

 _ctx = new HttpActionContext
        {
            ControllerContext = new HttpControllerContext()
            {
                Request = new HttpRequestMessage()

            }
        };
        _ctx.Request.Properties[System.Web.Http.Hosting.HttpPropertyKeys.HttpConfigurationKey] = new HttpConfiguration();
Run Code Online (Sandbox Code Playgroud)

诀窍是没有 Request.Properties 条目设置,它将显示以下错误:

请求没有关联的配置对象或提供的配置为空。

这可能是设计人员的疏忽,因为您可以在 HTTPActionContext 构造函数中设置 HTTPConfiguration!