You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为测试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"
    };
}

配置完成后:

  1. 请求的HasFormContentType返回true,跳过第一个异常判断
  2. 表单文件集合包含上传文件,跳过第二个异常判断
  3. 文件自身的ContentType为image/svg+xml,会进入目标处理分支

内容的提问来源于stack exchange,提问作者William Jockusch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 06:03:38