簡體   English   中英

測試 .net 內核 web api Z594C103F2C6E04C3D8AB059F031E0C 使用 XUnitCoreTestHost 文件上傳。

[英]Testing a .net core web api controller file upload using XUnit and AspNetCore.TestHost

我有這個 controller 來上傳文件:

[HttpPost]
public async Task<IActionResult> Post([FromForm] FileInformation fileInfo)
{
    int newFileVersion = 1;

    if (fileInfo == null || fileInfo.Files == null || fileInfo.Files.Count == 0)
        return BadRequest("File(s) not found");

    try
    {
        foreach (var locFile in fileInfo.Files)
        {
            //check for file extension, if not there, return an error
            var fileExtension = Path.GetExtension(locFile.FileName);
            if (string.IsNullOrEmpty(fileExtension))
                return BadRequest("Files must include file extension");


            var valid = await fileUtilities.IsFileValid(locFile);

            var newFileName = string.Concat(Guid.NewGuid().ToString(),valid.fileExtension);

            var newFileLocation = Path.Combine(config.GetSection("StoredFilePath").Value, newFileName);
           

            if (!valid.FileExtensionFound)
            {
                return BadRequest($"Error {valid.FileExtensionFoundError}");
            }
            if (!valid.FileSizeAllowed)
            {
                return BadRequest($"Error: {valid.FileSizeAllowedError}");
            }


            //check for an existing file in the database.  If there is one, increment the file version before the save
            var currentFile = await fileUtilities.FileExists(fileInfo, locFile);

            if (currentFile != null)
            {
                newFileVersion = currentFile.Version + 1;
            }
      
            //save to the file system
            using (var stream = new FileStream(newFileLocation, FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                await locFile.CopyToAsync(stream);
            }

            //save to the db.  Check to see if the file exists first.  If it does, do an insert, if not, return an error
            if (System.IO.File.Exists(newFileLocation))
            {
                FileUploads upload = new FileUploads
                {
                    EntityId = fileInfo.EntityId,
                    FileName = locFile.FileName,
                    ItemId = fileInfo.ItemId.ToString(),
                    NewFileName = newFileName,
                    ValidFile = true,
                    Version = newFileVersion
                };
                context.FileUploads.Add(upload);
                context.SaveChanges();
                //TODO: fire event the file has been saved provide Id key to find the record
                //upload.Id;
            }
            else
            {
                return BadRequest("Error: File Could not be saved");
            }

        }
    }
    catch (Exception ex)
    {
        return BadRequest("Failure to upload files.");
    }
    return Ok("File Uploaded");
}

我正在嘗試使用 XUnit 和Microsoft.AspNetCore.TestHost編寫單元文本,但我不知道如何編寫文件上傳測試。 這是我用來獲取錯誤請求的一項測試:

[Theory]
[InlineData("POST", "")]
public async Task LibrarianUploadFile_Error(string method, string? data = null)
{
    //arrange
    var request = new HttpRequestMessage(new HttpMethod(method), $"/api/librarian");

    //act
    var response = await _client.SendAsync(request);

    //assert
    Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}

這個測試通過了。 我已經為 GET 方法編寫了所有其他測試,沒有問題,我只是不知道如何進行此測試。 我在想我可以在我的本地測試機器上上傳一個測試文件,我只是不知道如何構建 POST。

這是我的 Class 的構造函數:

private readonly HttpClient _client;

public LibrarianUploadFiles()
{
    var configuration = new ConfigurationBuilder()
       .AddJsonFile("appsettings.json")
       .Build();

    var server = new TestServer(new WebHostBuilder()
        .UseConfiguration(configuration)
        .UseStartup<Startup>());
    _client = server.CreateClient();
}

這將創建我需要 GET、POST 等的客戶端。

這是問題的最終解決方案。 使用@gpaoli 的答案並環顧四周,我得到了這段代碼來發布並通過測試。

 //arrange
        var request = new HttpRequestMessage(new HttpMethod(method), [url to post]);

        using var form = new MultipartFormDataContent();
        using var fileContent = new ByteArrayContent(await File.ReadAllBytesAsync(@"c:\files\test.txt"));
        fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
        form.Add(fileContent, "Files", "test.txt");
        form.Add(new StringContent("Partner1"), "EntityId");
        form.Add(new StringContent(Guid.NewGuid().ToString()), "ItemId");

        //act
        HttpResponseMessage response;
        
        response = await _client.PostAsync($"/api/librarian", form);

        //assert

        Assert.Equal(HttpStatusCode.OK, response.StatusCode);

我遇到的幾個問題是添加 stringContent 並確保正確命名文件和字符串內容,以便 controller 可以 map 值。

您是否需要發布類似的帖子:

// Act
HttpResponseMessage response;

using (var file = File.OpenRead(@"path\fileName.txt"))
using (var content = new StreamContent(file))
using (var formData = new MultipartFormDataContent())
{
    formData.Add(content, "fileInfo", "fileName.txt");

    response = await client.PostAsync(url, formData);
}

// Assert
response.EnsureSuccessStatusCode(); 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM