Seb*_*n K 6 c# bdd unit-testing autofac asp.net-mvc-4
所以我正在使用 autofac 在 ASP.NET MVC 4 中编写一个高级单元测试。
所以我有一个示例控制器:
public class SomeController
{
[SomeFilter]
public ActionResult SomeAction()
{
SomeCode();
}
}
Run Code Online (Sandbox Code Playgroud)
我可以编写一个示例测试:
[Test]
public void Test()
{
var controller = new SomeController();
var result = controller.SomeAction();
// Asserts go here
}
Run Code Online (Sandbox Code Playgroud)
如果我伪造了所有外部依赖项,那么一切都很好。但是,还有一些通过 filter 属性附加的代码我想运行(这对这个测试很重要,我不想单独测试它)。
此代码将在应用程序中运行时执行,但如果在测试中运行则不会执行。我是否手动新建控制器或使用 DependencyResolver 检索它并不重要:
var someController = DependencyResolver.Current.GetService<SomeController>();
Run Code Online (Sandbox Code Playgroud)
这显然是因为在正常运行时框架会正确创建和附加这些过滤器。
所以问题是 - 我如何在测试中复制这种行为并执行这些动作过滤器?
由于除了在此处发布之外的原因,我还必须编写单元测试来利用操作过滤器以及 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);
Run Code Online (Sandbox Code Playgroud)
有两件事让我印象深刻。
我添加了屏幕截图,认为图片在这里会有帮助。