如何为测试ControllerContext添加FormFile并进入指定代码分支?
问题描述
尝试创建包含FormFile的ControllerContext对象用于测试控制器时,抛出System.InvalidOperationException异常(提示"Incorrect Content-Type: image/svg+xml")。
当前测试代码:
public static ControllerContext WithFiles(params IFormFile[] files) { var httpContext = new DefaultHttpContext(); foreach (var file in files) { var request = httpContext.Request; request.ContentType = "image/svg+xml"; // System.InvalidOperationException: 'Incorrect Content-Type: image/svg+xml' var form = request.Form; form.Files.Append(file); } var controllerContext = new ControllerContext { HttpContext = httpContext }; return controllerContext; }
待测试的控制器代码片段:
public async Task<IActionResult> ControllerMethod() { var file = HttpContext.Request.Form.Files[0]; byte[] buffer; if (!ContextAccessor.HttpContext.Request.HasFormContentType) throw new ConstraintException("Request MIME type is invalid."); if (ContextAccessor.HttpContext.Request.Form.Files.Count < 1) throw new ConstraintException("Attributes file not found."); if (file.ContentType == "image/svg+xml") { // 希望测试能进入此分支处理文件内容 } }
需要解决的问题:正确配置测试代码,让测试进入指定的if分支,同时确保文件包含有效内容。
解决方法
问题核心在于:文件上传的请求Content-Type必须是multipart/form-data(这是表单文件上传的标准类型),而image/svg+xml是文件自身的ContentType,不是请求的ContentType。直接给请求设置文件类型会导致表单解析失败,抛出异常。
具体修正步骤:
- 将请求的
ContentType设置为multipart/form-data,确保HasFormContentType返回true - 给每个
IFormFile对象单独设置ContentType为image/svg+xml - 手动构建表单集合并添加文件,避免直接操作
request.Form时的异常
修正后的测试代码:
public static ControllerContext WithFiles(params IFormFile[] files) { var httpContext = new DefaultHttpContext(); var formCollection = new FormCollection(new Dictionary<string, StringValues>(), new FormFileCollection()); foreach (var file in files) { // 确保文件自身的ContentType为image/svg+xml if (string.IsNullOrEmpty(file.ContentType)) { // 通过反射修改FormFile的私有ContentType字段(若创建文件时未指定) var contentTypeField = typeof(FormFile).GetField("_contentType", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); contentTypeField?.SetValue(file, "image/svg+xml"); } formCollection.Files.Add(file); } httpContext.Request.ContentType = "multipart/form-data"; httpContext.Request.Form = formCollection; return new ControllerContext { HttpContext = httpContext }; }
如果需要创建包含有效SVG内容的测试IFormFile实例,可以用以下工具方法:
public static IFormFile CreateTestSvgFile(string fileName = "test.svg") { // 构造有效SVG内容的内存流 var svgContent = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"100\" height=\"100\"><rect width=\"100\" height=\"100\" fill=\"red\"/></svg>"; var stream = new MemoryStream(Encoding.UTF8.GetBytes(svgContent)); return new FormFile(stream, 0, stream.Length, "file", fileName) { ContentType = "image/svg+xml" }; }
配置完成后:
- 请求的
HasFormContentType返回true,跳过第一个异常判断 - 表单文件集合包含上传文件,跳过第二个异常判断
- 文件自身的
ContentType为image/svg+xml,会进入目标处理分支
内容的提问来源于stack exchange,提问作者William Jockusch
相关产品推荐
相关产品推荐

