Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

xunit test for IFormFile field in Asp.net Core

I have an Asp.net Core method with below definition.

[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");
}

I want to create XUnit Test for this function, how could I mock IFormFile?

Update:

Controller:

[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();
}

Xunit Test

[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));
}

But, I got empty image in the target path.

like image 823
Edward Avatar asked May 23 '17 08:05

Edward


People also ask

How do you write xUnit test cases in .NET core?

To write a test you simply create a public method that returns nothing and then decorate it with the Fact attribute. Inside that method you can put whatever code you want but, typically, you'll create some object, do something with it and then check to see if you got the right result using a method on the Assert class.

What is IFormFile in asp net core?

What is IFormFile. ASP.NET Core has introduced an IFormFile interface that represents transmitted files in an HTTP request. The interface gives us access to metadata like ContentDisposition, ContentType, Length, FileName, and more. IFormFile also provides some methods used to store files.

Is xUnit a test runner?

The MSBuild runner in xUnit.net v2 is capable of running unit tests from both xUnit.net v1 and v2. It can run multiple assemblies at the same time, and build file options can be used to configuration the parallelism options used when running the tests.


1 Answers

When testing with IFormFile dependencies, mock the minimal necessary members to exercise the test. In the Controller above FileName property and CopyToAsync method are used. Those should be setup for the test.

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();
    //...
}

Though mentioned in the comments that the question is just a demo, the tight coupling to the file system should be abstracted to allow for better flexibility

like image 142
Nkosi Avatar answered Sep 25 '22 21:09

Nkosi