繁体   English   中英

如何将控制器与过滤器一起单元测试(带有autofac的ASP.NET MVC)

[英]How can I unit test controller together with a filter (ASP.NET MVC with autofac)

所以我正在使用autofac在ASP.NET MVC 4中编写高级单元测试。

所以我有一个样本控制器:

    public class SomeController
    {        
        [SomeFilter]
        public ActionResult SomeAction()
        {
            SomeCode();
        }
    }

我可以写一个样本测试:

    [Test]
    public void Test()
    {
        var controller = new SomeController();
        var result = controller.SomeAction();
        // Asserts go here
    }

只要我伪造出所有外部依赖关系,这一切都很有效。 但是,还有一些代码通过我希望运行的filter属性附加(这对于此测试很重要,我不想只是单独测试它)。

此代码将在应用程序中运行时执行,但如果在测试中运行则不会执行。 如果我手动启动控制器,或使用DependencyResolver检索它,则无关紧要:

var someController = DependencyResolver.Current.GetService<SomeController>();

这显然是因为在正常运行时,框架会正确创建和附加这些过滤器。

所以问题是 - 如何在测试中复制此行为并执行这些操作过滤器?

早安塞巴斯蒂安,

由于此处发布的原因,我不得不编写单元测试以使用动作过滤器以及web api控制器端点。

当然,正如您观察到的那样,我发现动作过滤器在单元测试期间不会触发。

我讨厌这个解决方案,但我肯定对接受进一步的教育持开放态度。

在我的单元测试中,我使用的是流畅的构建器模式,但总之是旋转控制器。 (顺便说一句,如果你想要更多关于流畅的建设者模式的信息,只需发表评论,我会传递链接......或谷歌。)

//we need to setup some context stuff that you'll notice is passed 
//in to the builder WithControllerContext...and then the controller is 
//used to get the ActionFilter primed

//0. Setup WebApi Context
var config = new HttpConfiguration();
var route = config.Routes.MapHttpRoute("DefaultSlot", "cars/_services/addPickup");
var routeData = new HttpRouteData(route, new HttpRouteValueDictionary { { "controller", "AddPickup" } });


var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost:24244/cars/_services/addPickup");
request.RequestUri = new Uri("http://localhost:24244/cars/_services/addPickup");
List<string> x = new List<string>() { MediaType.CarsV2.GetDescription() };
request.Headers.Add("Accept", x);


 ....obviously 1 & 2 I skipped as they aren't relevant


//3. controller
PickupController controller = new PickupControllerBuilder()
//.MoqReqHlpr_IsAny_CreateResp(HttpStatusCode.OK) //3a. setup return message
.MoqCarRepoAny_ReturnsSampleDataCar(new Guid("000...0011")) //3b. car object
.MoqFulfillRepoAnyCar_IsAny_IsQuickShop(true) //3c. fulfillment repository
.MoqCartRepoAnyCar_IsAny_UpdateCar(true) //3d. car repository
.WithControllerContext(config, routeData, request)
.WithHttpPropertyKey(lsd);


//HttpActionContextFilter is the name of my ActionFilter so as you can
//see we actually instantiate the ActionFilter then hook it to the
//controller instance
var filter = new HttpActionContextFilter();
filter.OnActionExecuting(controller.ActionContext);

咬我的两件事要注意。

  1. 确保你有正确的命名空间。 我让VS通过Ctrl-导入它。 当然它导入了System.Web.Mvc,我需要System.Web.Http。
  2. 你需要挂钩你想要触发的覆盖。 因此,如果您的动作过滤器有四个覆盖,那么您需要挂钩四次。 如果你有多个ActionFilters,那么你需要实例化每个并挂钩它的覆盖。

我提供了截图,认为图片在这里会有所帮助。

在此输入图像描述

暂无
暂无

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

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