Как смоделировать IFormFile для модульного / интеграционного теста в ASP.NET Core 1 MVC 6?

Я хочу написать тесты для загрузки файлов в ASP.NET Core 1, но не могу найти хороший способ для макета / создания экземпляра объекта, полученного из IFormFile. Любые предложения о том, как это сделать?

Благодарю.

6 ответов

Решение

Предполагая, что у вас есть контроллер, как..

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

...где IFormFile.OpenReadStream() Доступ с помощью тестируемого метода. Вы можете создать тест с использованием Moq Mocking Framework для симуляции потоковых данных.

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

Еще один быстрый и dirty способ добиться этого будет создать фактический экземпляр

 IFormFile file = new FormFile(new MemoryStream(Encoding.UTF8.GetBytes("This is a dummy file")), 0, 0, "Data", "dummy.txt");

Добавление ответа harishr с заданной длиной (это было то, что мне нужно для работы моего Blob.Upload()).

private IFormFile CreateTestFormFile(string p_Name, string p_Content)
{
    byte[] s_Bytes = Encoding.UTF8.GetBytes(p_Content);

    return new FormFile(
        baseStream: new MemoryStream(s_Bytes),
        baseStreamOffset: 0,
        length: s_Bytes.Length,
        name: "Data",
        fileName: p_Name
    );
}

Я не мог издеваться над IFormFile, потому что у меня была проблема с Stream, поэтому я создал экземпляр FormFile. Если вы используете валидаторы и т. Д. Для файла, имейте в виду, что вам нужно установить тип содержимого.

              private IFormFile GetFileMock(string contentType, string content)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(content);

            var file = new FormFile(
                baseStream: new MemoryStream(bytes),
                baseStreamOffset: 0,
                length: bytes.Length,
                name: "Data",
                fileName: "dummy.csv"
            )
            {
                Headers = new HeaderDictionary(),
                ContentType = contentType
            };

            return file;
        }
        

звонить

       GetFileMock("text/csv", "test;test;")
      private static IFormFileCollection GetFormFileCollection()
{
    var filesFolder = $"{AppDomain.CurrentDomain.SetupInformation.ApplicationBase}UploadFiles\\";
    List<string> filesPathsListToUpload = new List<string>();
    filesPathsListToUpload.Add($"{filesFolder}UploadFile1.png");
    filesPathsListToUpload.Add($"{filesFolder}UploadFile2.jpg");
    filesPathsListToUpload.Add($"{filesFolder}UploadFile3.bmp");

    FormFileCollection filesCollection = new FormFileCollection();
    foreach (var filePath in filesPathsListToUpload)
    {
        var stream = File.OpenRead(filePath);
        IFormFile file = new FormFile(stream, 0, stream.Length, "files", Path.GetFileName(filePath))
        {
            Headers = new HeaderDictionary(),
            ContentType = filePath.Split('.')[1] == "jpg" ? "image/jpeg"
                : filePath.Split('.')[1] == "png" ? "image/png"
                : "image/bmp",
        };
        
        filesCollection.Add(file);
    }

    var httpContext = new DefaultHttpContext();
    httpContext.Request.Headers.Add("Content-Type", "multipart/form-data");
    httpContext.Request.Form = new FormCollection(new Dictionary<string, StringValues>(), filesCollection);

    return httpContext.Request.Form.Files;
}

Я использую этот сниппет для своих интеграционных тестов

      public static MultipartFormDataContent CreateTestFile(string fileName, string fileContent)
        {
            var content = new MultipartFormDataContent();
            content.Add(new ByteArrayContent(Encoding.UTF8.GetBytes(fileContent)), "files", fileName);
            return content;
        }

И вот как я использую его со своими интеграционными тестами.

      [Fact]
        public async Task UploadDocument_ReturnsOk()
        {
            // Arrange
            var provider = TestClaimsProvider.WithUserClaims();
            var client = _factory.CreateClientWithTestAuth(provider);

            // Act
            HttpResponseMessage? resultResponseMessage = await client.PutAsync($"/api/Documents",
                WebApiExtensions.CreateTestFile("test.csv", "content"));

            // Assert
            resultResponseMessage.ShouldHave200Code();
        }
Другие вопросы по тегам