Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock an IFormFile for a unit/integration test in ASP.NET Core?

I want to write tests for uploading of files in ASP.NET Core but can't seem to find a nice way to mock/instantiate an object derived from IFormFile.

Any suggestions on how to do this?

like image 681
Kasper P Avatar asked Apr 26 '16 07:04

Kasper P


People also ask

Which method is used in the unit testing application in .NET core?

The Assert. Equal() method is a quick way to check whether an expected result is equal to a returned result. If they are equal, the test method will pass. Otherwise, the test will fail.


2 Answers

Assuming you have a Controller like..

public class MyController : Controller {
    public Task<IActionResult> UploadSingle(IFormFile file) {...}
}

...where the IFormFile.OpenReadStream() is accessed with the method under test.

As of ASP.NET Core 3.0, use an instance of the FormFile Class which is now the default implementation of IFormFile.

Here is an example of the same test above using FormFile class

[TestClass]
public class IFormFileUnitTests {
    [TestMethod]
    public async Task Should_Upload_Single_File() {
        //Arrange
       
        //Setup mock file using a memory stream
        var content = "Hello World from a Fake File";
        var fileName = "test.pdf";
        var stream = new MemoryStream();
        var writer = new StreamWriter(stream);
        writer.Write(content);
        writer.Flush();
        stream.Position = 0;

        //create FormFile with desired data
        IFormFile file = new FormFile(stream, 0, stream.Length, "id_from_form", fileName);
        
        MyController sut = new MyController();
        
        //Act
        var result = await sut.UploadSingle(file);

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

Before the introduction of the FormFile Class or in in cases where an instance is not needed you can create a test using Moq mocking framework to simulate the stream data.

[TestClass]
public class IFormFileUnitTests {
    [TestMethod]
    public async Task Should_Upload_Single_File() {
        //Arrange
        var fileMock = new Mock<IFormFile>();
        //Setup mock file using a memory stream
        var content = "Hello World from a Fake File";
        var fileName = "test.pdf";
        var ms = new MemoryStream();
        var writer = new StreamWriter(ms);
        writer.Write(content);
        writer.Flush();
        ms.Position = 0;
        fileMock.Setup(_ => _.OpenReadStream()).Returns(ms);
        fileMock.Setup(_ => _.FileName).Returns(fileName);
        fileMock.Setup(_ => _.Length).Returns(ms.Length);

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

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

        //Assert
        Assert.IsInstanceOfType(result, typeof(IActionResult));
    }
}
like image 87
Nkosi Avatar answered Oct 22 '22 09:10

Nkosi


Easier would be to create an actual in-memory instance

 var bytes = Encoding.UTF8.GetBytes("This is a dummy file");
 IFormFile file = new FormFile(new MemoryStream(bytes), 0, bytes.Length, "Data", "dummy.txt");
like image 52
harishr Avatar answered Oct 22 '22 08:10

harishr