Comment pouvez-vous tester un filtre d’action dans ASP.NET Web Api?

Je cherchais à append un filtre d’action à mon service pour gérer l’ajout de données de lien au message de réponse. J’ai trouvé que je devais me moquer de HttpActionExecutedContext mais c’est une classe difficile de se moquer, comment gérez-vous les tests de filtre d’action?

    Vous pouvez créer un faux pour HttpActionExecutedContext comme ci-dessous:

     public static HttpActionContext CreateActionContext(HttpControllerContext controllerContext = null, HttpActionDescriptor actionDescriptor = null) { HttpControllerContext context = controllerContext ?? ContextUtil.CreateControllerContext(); HttpActionDescriptor descriptor = actionDescriptor ?? new Mock() { 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; } 

    Je viens de copier et coller ce code à partir du code source de l’API Web ASP.NET: classe ContextUtil . Voici quelques exemples sur la façon dont ils ont testé des filtres intégrés:

    • AuthorizeAtsortingbuteTest

    • ActionFilterAtsortingbuteTest

    ActionFilterAtsortingbuteTest est la classe de test pour ActionFilterAtsortingbute qui est une classe abstraite mais vous en aurez l’idée.

    Juste un nouveau.

     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 SsortingngContent("blah") } }; } 

    J’ai eu le même problème en essayant de tester un filtre d’exception non géré personnalisé que j’avais construit.

    Cela a fait l’affaire. Beaucoup de nouveautés et une très longue ligne de code.

     var httpActionExecutedContext = new HttpActionExecutedContext( new HttpActionContext( new HttpControllerContext( new HttpConfiguration(), Substitute.For(), new HttpRequestMessage()), Substitute.For()), null); 

    NSubstiute a été utilisé, mais tout cadre moqueur de votre choix qui gère les classes de base abstraites conviendrait.

    J’espère que cela t’aides

    Je me suis cogné la tête contre un mur de briques. J’ai essayé contextUtil mais j’ai continué à obtenir une exception de référence null. J’ai trouvé comment appeler un actionFilter dans ce post NB L’actionFilter n’était pas invoqué lors de l’utilisation d’une instance Mock du filtre, je devais utiliser l’object réel. HTH

    Plus précisément:

     var httpActionContext = new HttpActionContext { ControllerContext = new HttpControllerContext { Request = requestMessage } }; //call filter var filter = new FooFilter(); filter.OnActionExecuting(httpActionContext); 

    Voici un exemple de travail de 2018 (.NET Framework 4.5.1). Il utilise un ExceptionFilterAtsortingbute mais il devrait être similaire pour les autres FilterAtsortingbutes.

     [Test] public void MyTest() { var request = new HttpRequestMessage(HttpMethod.Get, new Uri("http://www.google.com")); var response = new HttpResponseMessage(); // This next line is necessary to avoid the following error // if you call `context.Request.CreateResponse(...)` inside the filter: // System.InvalidOperationException: The request does not have an associated configuration object or the provided configuration was null. // Discovered from https://stackoverflow.com/a/44447355/3312114 request.SetConfiguration(new HttpConfiguration()); var context = ContextUtil.GetActionExecutedContext(request, response); _myFilter.OnException(context); // Execute your methods Assert.AreEqual(HttpStatusCode.InternalServerError, context.Response.StatusCode); // Make your assertions } 

    Ensuite, copiez simplement la classe ContextUtil dans votre projet de test quelque part. Le commentaire de @ thomasb sur la réponse de @tugberk suggère que le dernier code est sur Codeplex . Bien que ce commentaire fût en 2014, il pourrait même y avoir un code plus tard, le code de 2014 a fonctionné pour moi (en janvier 2018) alors que le code lié d’origine ne l’était pas. J’ai copié la version ultérieure ci-dessous pour plus de commodité. Il suffit de déposer ce fichier dans un nouveau fichier.

     internal static class ContextUtil { public static HttpControllerContext CreateControllerContext(HttpConfiguration configuration = null, IHttpController instance = null, IHttpRouteData routeData = null, HttpRequestMessage request = null) { HttpConfiguration config = configuration ?? new HttpConfiguration(); IHttpRouteData route = routeData ?? new HttpRouteData(new HttpRoute()); HttpRequestMessage req = request ?? new HttpRequestMessage(); req.SetConfiguration(config); req.SetRouteData(route); HttpControllerContext context = new HttpControllerContext(config, route, req); if (instance != null) { context.Controller = instance; } context.ControllerDescriptor = CreateControllerDescriptor(config); return context; } public static HttpActionContext CreateActionContext(HttpControllerContext controllerContext = null, HttpActionDescriptor actionDescriptor = null) { HttpControllerContext context = controllerContext ?? ContextUtil.CreateControllerContext(); HttpActionDescriptor descriptor = actionDescriptor ?? CreateActionDescriptor(); descriptor.ControllerDescriptor = context.ControllerDescriptor; return new HttpActionContext(context, descriptor); } public static HttpActionContext GetHttpActionContext(HttpRequestMessage request) { HttpActionContext actionContext = CreateActionContext(); actionContext.ControllerContext.Request = request; return actionContext; } 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; } public static HttpControllerDescriptor CreateControllerDescriptor(HttpConfiguration config = null) { if (config == null) { config = new HttpConfiguration(); } return new HttpControllerDescriptor() { Configuration = config, ControllerName = "FooController" }; } public static HttpActionDescriptor CreateActionDescriptor() { var mock = new Mock() { CallBase = true }; mock.SetupGet(d => d.ActionName).Returns("Bar"); return mock.Object; } }