【问题标题】:Http response headers parser fails when returning FileContentResult in unit test在单元测试中返回 FileContentResult 时,Http 响应标头解析器失败
【发布时间】:2019-08-07 11:51:50
【问题描述】:

我正在尝试为以下 AspNetCore 控制器方法编写单元测试:

[HttpGet]
public async Task<IActionResult> GetFile(string id)
{
    FileContent file = await fileRepository.GetFile(id);

    if (file == null)
        return NotFound();

    Response.Headers.Add("Content-Disposition", file.FileName);

    return File(file.File, file.ContentType);
}

文件内容类:

public class FileContent
{
    public FileContent(string fileName, string contentType, byte[] file)
    {
        FileName = fileName;
        ContentType = contentType;
        File = file;
    }

    public string FileName { get; }
    public string ContentType { get; }
    public byte[] File { get; }
}

这里是TestInitialize:

[TestInitialize]
public void TestInitialize()
{
    repositoryMock = new Mock<IFileRepository>();
    controller = new FilesController(repositoryMock.Object);
    var httpContext = new Mock<HttpContext>(MockBehavior.Strict);
    var response = new Mock<HttpResponse>(MockBehavior.Strict);
    var headers = new HeaderDictionary();
    response.Setup(x => x.Headers).Returns(headers);
    httpContext.SetupGet(x => x.Response).Returns(response.Object);
    controller.ControllerContext = new ControllerContext(new ActionContext(httpContext.Object, new RouteData(), new ControllerActionDescriptor()));
}

及测试方法:

[TestMethod]
public async Task GetShouldReturnCorrectResponse()
{
    repositoryMock
        .Setup(x => x.GetFile(It.IsAny<string>(), null))
        .ReturnsAsync(new FileContent("test.txt", "File Content.", Encoding.UTF8.GetBytes("File Content.")));

    IActionResult response = await controller.GetFile(DocumentId);

    // .. some assertions
}

以下控制器线路上的测试失败:

return File(file.File, file.ContentType);

例外:

System.FormatException:标头在索引 0 处包含无效值: “文件内容。” 在 Microsoft.Net.Http.Headers.HttpHeaderParser`1.ParseValue(StringSegment 值,Int32& 索引)在 Microsoft.AspNetCore.Mvc.FileContentResult..ctor(字节 [] 文件内容, 字符串内容类型)在 Microsoft.AspNetCore.Mvc.ControllerBase.File(Byte[] fileContents, String contentType, String fileDownloadName)

我不知道这里出了什么问题。请指教。

【问题讨论】:

    标签: c# unit-testing asp.net-core


    【解决方案1】:

    当您向响应中添加标头时,ASP.NET Core 将验证已知标头以确保它们包含有效值。在您的情况下,您尝试在此处将内容类型设置为 "File Content."

    repositoryMock
        .Setup(x => x.GetFile(It.IsAny<string>(), null))
        .ReturnsAsync(new FileContent("test.txt", "File Content.", Encoding.UTF8.GetBytes("File Content.")));
    //                                            ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
    

    File Content. 不是有效的MIME type,因此该值的验证失败。

    相反,您应该使用实际的 MIME 类型,例如text/plain 因为您的测试中也有纯文本内容:

    repositoryMock
        .Setup(x => x.GetFile(It.IsAny<string>(), null))
        .ReturnsAsync(new FileContent("test.txt", "text/plain", Encoding.UTF8.GetBytes("File Content.")));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多