我有一个物理文件,我想把它传递给需要IFormFile类型(用于单元测试)的controller方法。
我找不到任何实例化IFormFile接口的类,这意味着我无法创建一个。
如何将物理文件转换为IFormFile

最佳答案

假设有一个控制器方法可以接受IFormInfo

[HttpPost]
public Task<IActionResult> Upload(IFormFile file) {

    FileDetails fileDetails = null;
    using (var reader = new StreamReader(file.OpenReadStream())) {
        var fileContent = reader.ReadToEnd();
        ContentDispositionHeaderValue parsedContentDisposition = null;
        if (ContentDispositionHeaderValue.TryParse(file.ContentDisposition, out parsedContentDisposition)) {
            fileDetails = new FileDetails {
                Filename = parsedContentDisposition.FileName,
                Content = fileContent
            };
        }
    }

    return Task.FromResult((IActionResult)fileDetails);

}

使用moq这样的模拟框架。您可以使用物理文件模拟IFormFile
[TestMethod]
public async Task Controller_Should_Upload_FormFile() {
    // Arrange.
    var fileMock = new Mock<IFormFile>();
    var physicalFile = new FileInfo("filePath");
    var ms = new MemoryStream();
    var writer = new StreamWriter(ms);
    writer.Write(physicalFile.OpenRead());
    writer.Flush();
    ms.Position = 0;
    var fileName = physicalFile.Name;
    //Setup mock file using info from physical file
    fileMock.Setup(_ => _.FileName).Returns(fileName);
    fileMock.Setup(_ => _.Length).Returns(ms.Length);
    fileMock.Setup(_ => _.OpenReadStream()).Returns(ms);
    fileMock.Setup(_ => _.ContentDisposition).Returns(string.Format("inline; filename={0}", fileName));
    //...setup other members as needed.

    var sut = new MyController();
    var file = fileMock.Object;

    // Act.
    var result = await sut.Upload(file);

    //Assert.
    Assert.IsInstanceOfType(result, typeof(IActionResult));
}

模拟的排列甚至可以提取为可重用的扩展方法。
public static IFormFile AsMockIFormFile(this FileInfo physicalFile) {
    var fileMock = new Mock<IFormFile>();
    var ms = new MemoryStream();
    var writer = new StreamWriter(ms);
    writer.Write(physicalFile.OpenRead());
    writer.Flush();
    ms.Position = 0;
    var fileName = physicalFile.Name;
    //Setup mock file using info from physical file
    fileMock.Setup(_ => _.FileName).Returns(fileName);
    fileMock.Setup(_ => _.Length).Returns(ms.Length);
    fileMock.Setup(m => m.OpenReadStream()).Returns(ms);
    fileMock.Setup(m => m.ContentDisposition).Returns(string.Format("inline; filename={0}", fileName));
    //...setup other members (code removed for brevity)


    return fileMock.Object;
}

使用起来像
var physicalFile = new FileInfo("filePath");
IFormFile formFile = physicalFile.AsMockIFormFile();

关于c# - 从物理文件实例化IFormFile,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37628743/

10-11 15:09