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

如何用xUnit测试文件上传API?解决FormFile属性缺失问题

解决测试中FormFile属性缺失导致的验证失败问题

核心问题

你手动创建的FormFile实例缺少真实请求中自动填充的ContentType、Headers等属性,触发了服务层的文件类型验证异常。

解决步骤

  1. 读取真实文件流并设置ContentType
    不要使用空的MemoryStream,读取测试文件的真实内容到流中,同时显式指定ContentType为text/csv。

  2. 手动构造请求头信息
    为FormFile添加Content-Disposition头,模拟真实表单提交时的请求头结构。

  3. 修正程序集路径获取逻辑
    测试环境中Assembly.GetEntryAssembly()可能返回null,改用当前测试类的程序集定位文件路径,避免空引用异常。

修改后的测试代码示例

[Theory]
[InlineData("REPORT_DETAILS_TEST.csv")]
public async Task CreateReport_CreateSuccessfully(string fileName)
{
    // Arrange
    using var context = new DataContext(TestHelper.CreateMockDbOptions());
    var repository = new MyRepository(context);
    var service = new MyService(repository, _mapper);
    var controller = new MyController(service);

    // 改用当前测试类的程序集获取路径,避免GetEntryAssembly返回null
    var testAssembly = typeof(YourTestClassName).Assembly;
    var assemblyPath = Path.GetDirectoryName(testAssembly.Location)!;
    var filePath = Path.Combine(assemblyPath, "Assets", fileName);

    // 读取真实文件内容到内存流
    var fileBytes = await File.ReadAllBytesAsync(filePath);
    var fileStream = new MemoryStream(fileBytes);

    // 创建FormFile并设置ContentType
    var formFile = new FormFile(fileStream, 0, fileBytes.Length, "FileUploaded", Path.GetFileName(filePath))
    {
        ContentType = "text/csv"
    };

    // 添加Content-Disposition请求头,模拟真实表单提交
    formFile.Headers = new HeaderDictionary();
    formFile.Headers.Add(
        "Content-Disposition",
        $"form-data; name=\"FileUploaded\"; filename=\"{Path.GetFileName(filePath)}\""
    );

    var inputFile = new FileUploadRequest { FileUploaded = formFile };

    // Act
    var result = await controller.CreateReport(inputFile);

    // Assert
    Assert.NotNull(result);
    // 可添加更多断言验证返回结果
    var createdResult = Assert.IsType<CreatedResult>(result);
    var response = Assert.IsType<IdResponse>(createdResult.Value);
    Assert.NotNull(response.Id);
}

额外提示

你的服务层代码存在一处错误:

IEnumerable<ReportDetailDbModel> details = _mapper.Map<IEnumerable<ReportDetailDbModel>>(details);

映射参数details未定义,应改为reportDetails,否则运行时会抛出异常:

IEnumerable<ReportDetailDbModel> details = _mapper.Map<IEnumerable<ReportDetailDbModel>>(reportDetails);

内容的提问来源于stack exchange,提问作者Nguyen Quoc Bao

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 13:16:19