c# - 我如何将 Controller 与过滤器一起进行单元测试(带有 autofac 的 ASP.NET MVC)

标签 c# unit-testing asp.net-mvc-4 bdd autofac

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

所以我有一个示例 Controller :

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

我可以写一个示例测试:

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

一切都很好,前提是我伪造了所有外部依赖项。 但是,还有一些我想运行的通过 filter 属性附加的代码(这对这个测试很重要,我不想单独测试它)。

此代码在应用程序中运行时会执行,但在测试中运行时不会执行。无论我是手动新建 Controller ,还是使用 DependencyResolver 检索它都没有关系:

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

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

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

最佳答案

早上好塞巴斯蒂安

由于无法在此处发布的原因,我不得不编写单元测试以利用操作过滤器和 Web API Controller 端点。

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

我通过黑客攻击找到了这个解决方案,但绝对愿意接受进一步的教育。

在我的单元测试中,我使用了流畅的构建器模式,但总之启动了您的 Controller 。 (顺便说一句,如果您想了解有关流式构建器模式的更多信息,只需发表评论,我会传递链接……或者谷歌。)

//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. 您需要 Hook 要触发的覆盖。所以如果你的 Action 过滤器 有四个覆盖,那么你需要 Hook 四次。如果您有多个 ActionFilters,那么您需要实例化每个 ActionFilters 并 Hook 其覆盖。

我附上了屏幕截图,认为图片在这里会有帮助。

enter image description here

关于c# - 我如何将 Controller 与过滤器一起进行单元测试(带有 autofac 的 ASP.NET MVC),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23500635/

相关文章:

java - 使用 SparseIntArray 和其他来自 android.util.* 的本地单元测试

c# - 使用 ASP.NET MVC Identity 2.0 播种和登录默认用户的合适位置在哪里?

c# - 带有解析数据的 ASP.NET MVC 4

c# - c# 中的可绑定(bind)对象?

c# - 在循环中创建位图时出现内存溢出异常

unit-testing - 如何在Dart中对大量异步流程进行单元测试?

asp.net-mvc - 如何在 ASP.NET MVC API Controller 中获取用户 IP

c# - C# 中的可选参数 - 将用户定义的类默认为 null

c# - 不受约束的旋律错误

Objective-C:用于测试目的的 NSInputStream 和 NSOutputStream