.NET Framework转.NET Core 2.1:自定义过滤器属性单元测试适配
在.NET Core 2.1中测试自定义ActionFilterAttribute的正确姿势
你遇到的问题本质是.NET Core MVC和.NET Framework MVC的Action上下文类结构差异导致的——原来的HttpActionContext、HttpControllerContext这些类型在.NET Core里已经被重构替换了,不过测试自定义ActionFilterAttribute的思路完全可行,只需要适配新的API来构建测试上下文。
下面给你一套适配.NET Core 2.1的测试代码,完美对应你原来的测试逻辑(沿用你熟悉的MSTest风格):
测试类初始化与上下文构建
private ActionExecutingContext _successContext; private ActionExecutingContext _failContext; [TestInitialize] public void Initialize() { // 1. 构建基础HTTP上下文与控制器上下文 var httpContext = new DefaultHttpContext(); var controllerContext = new ControllerContext { HttpContext = httpContext }; // 2. 构建Action描述器:.NET Core上下文必须依赖这个,用空测试Controller填充即可 var actionDescriptor = new ControllerActionDescriptor { ControllerTypeInfo = typeof(DummyTestController).GetTypeInfo(), ActionName = "TestAction" }; // 3. 构建ModelState无错误的成功场景上下文 var successModelState = new ModelStateDictionary(); successModelState.Add("TestField", new ModelState()); _successContext = new ActionExecutingContext( controllerContext, actionDescriptor, new Dictionary<string, object>(), // 无Action参数时传空字典 new DummyTestController()) { ModelState = successModelState }; // 4. 构建带错误的失败场景上下文 var failModelState = new ModelStateDictionary(); failModelState.Add("TestField", new ModelState()); failModelState.AddModelError("TestField", "Test error message"); _failContext = new ActionExecutingContext( controllerContext, actionDescriptor, new Dictionary<string, object>(), new DummyTestController()) { ModelState = failModelState }; } // 定义一个空的测试用Controller,用于填充上下文的类型信息 private class DummyTestController : Controller { }
测试方法示例
[TestMethod] public void OnActionExecuting_ModelStateValid_DoesNotSetResult() { // Arrange var attribute = new JsonValidationFilterAttribute(); // Act attribute.OnActionExecuting(_successContext); // Assert Assert.IsNull(_successContext.Result); } [TestMethod] public void OnActionExecuting_ModelStateInvalid_ReturnsBadRequestWithErrors() { // Arrange var attribute = new JsonValidationFilterAttribute(); // Act attribute.OnActionExecuting(_failContext); // Assert var badRequestResult = _failContext.Result as BadRequestObjectResult; Assert.IsNotNull(badRequestResult); Assert.AreEqual((int)HttpStatusCode.BadRequest, badRequestResult.StatusCode); var errorMessages = badRequestResult.Value as IEnumerable<string>; Assert.IsNotNull(errorMessages); Assert.AreEqual("Test error message", errorMessages.First()); }
关键差异说明
对比你原来的.NET Framework测试代码,核心变化点:
- 用
ActionExecutingContext替代了HttpActionContext,这是.NET Core MVC中Action过滤器的标准上下文类型 HttpControllerContext被替换为ControllerContext,构建时需要传入DefaultHttpContext模拟HTTP请求环境- 必须提供
ActionDescriptor,因为.NET Core的上下文依赖这个识别当前Action信息,用空测试Controller填充即可 - 验证结果时,不再检查
Response,而是检查Result属性,对应你Attribute里的BadRequestObjectResult逻辑
这种测试自定义ActionFilter的方法在.NET Core里完全适用,只要按照新的API构建好上下文对象,就能正常验证你的Attribute逻辑。
内容的提问来源于stack exchange,提问作者Ctrl_Alt_Defeat
相关产品推荐
相关产品推荐

