在Asp.net Core中对IFormFile字段进行xunit测试

Tao*_*hou 5 c# unit-testing moq xunit asp.net-core

我有一个Asp.net Core方法具有以下定义。

[HttpPost]
public IActionResult Upload(IFormFile file)
{
    if (file == null || file.Length == 0)
        throw new Exception("file should not be null");

    var originalFileName = ContentDispositionHeaderValue
        .Parse(file.ContentDisposition)
        .FileName
        .Trim('"');

    file.SaveAs("your_file_full_address");
}
Run Code Online (Sandbox Code Playgroud)

我想为此功能创建XUnit Test,该如何模拟IFormFile

更新:

控制器:

[HttpPost]
public async Task<ActionResult> Post(IFormFile file)
{

    var path = Path.Combine(@"E:\path", file.FileName);

    using (var stream = new FileStream(path, FileMode.Create))
    {
        await file.CopyToAsync(stream);
    }
    return Ok();
}
Run Code Online (Sandbox Code Playgroud)

Xunit测试

[Fact]
public async void Test1()
{
    var file = new Mock<IFormFile>();
    var sourceImg = File.OpenRead(@"source image path");
    var stream = new MemoryStream();
    var writer = new StreamWriter(stream);
    writer.Write(sourceImg);
    writer.Flush();
    stream.Position = 0;
    var fileName = "QQ.png";
    file.Setup(f => f.OpenReadStream()).Returns(stream);
    file.Setup(f => f.FileName).Returns(fileName);
    file.Setup(f => f.Length).Returns(stream.Length);

    var controller = new ValuesController();
    var inputFile = file.Object;

    var result = await controller.Post(inputFile);

    //Assert.IsAssignableFrom(result, typeof(IActionResult));
}
Run Code Online (Sandbox Code Playgroud)

但是,我在目标路径中没有图像。

Nko*_*osi 6

使用IFormFile依赖项进行测试时,请模拟最少的成员以进行测试。在Controller中,使用以上FileName属性和CopyToAsync方法。这些应该为测试设置。

public async Task Test1() {
    // Arrange.
    var file = new Mock<IFormFile>();
    var sourceImg = File.OpenRead(@"source image path");
    var ms = new MemoryStream();
    var writer = new StreamWriter(ms);
    writer.Write(sourceImg);
    writer.Flush();
    ms.Position = 0;
    var fileName = "QQ.png";
    file.Setup(f => f.FileName).Returns(fileName).Verifiable();
    file.Setup(_ => _.CopyToAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
        .Returns((Stream stream, CancellationToken token) => ms.CopyToAsync(stream))
        .Verifiable();

    var controller = new ValuesController();
    var inputFile = file.Object;

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

    //Assert.
    file.Verify();
    //...
}
Run Code Online (Sandbox Code Playgroud)

尽管在评论中提到该问题只是一个演示,但应抽象出与文件系统的紧密耦合,以实现更好的灵活性


har*_*shr 5

你可以像这样创建一个实际的实例......

IFormFile file = new FormFile(new MemoryStream(Encoding.UTF8.GetBytes("dummy image")), 0, 0, "Data", "image.png");
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的简短解决方案。但是第三个参数应该大于0,否则file.Length将为零 (3认同)