C# XUnit (.Net 8):要测试的端点中的 IFormFile 参数始终接收为 null

问题描述 投票:0回答:1

我需要 XUnit 测试下一个端点:

/// <summary>
/// Cease all account in csv file
/// </summary>
/// <param name="dispatcher"></param>
/// <param name="csvFile">CSV file with format (Id,Name,SID,CeaseDate,Note)</param>
/// <param name="ct"></param>
/// <returns></returns>
[HttpPost("cease/bulk")]
[Authorize(Roles = VdcSecurity.Role.ManagementAdmin)]
[AllowAnonymous]
public async Task<ActionResult<bool>> CeaseBulkAccountAsync(
    [FromServices][IsSensitive] ICommandDispatcher dispatcher, 
    [FromForm] IFormFile csvFile,
    [IsSensitive] CancellationToken ct = default
)
{
    var identity = Vdc.Libs.AspNet.Controller.HttpContextExtensions.GetIdentity(HttpContext);
    var ipAddress = HttpContext.GetIpAddress();

    var command = new CeaseBulkCommand(identity, HttpContext.TraceIdentifier)
    {
        Stream = csvFile.OpenReadStream(),
        IpAddress = ipAddress
    };
    var result = await dispatcher.DispatchAsync(_provider, command, ct);

    return result.ToActionResult(this);
}

我的问题是无论我如何创建 IFormFile 对象,它总是被接收为 null。

这是我的尝试之一:

const string filePath = "CeaseBulkAccount.csv";

using (var httpClient = ApiClient.HttpClient)
{
    var form = new MultipartFormDataContent();

    byte[] fileData = File.ReadAllBytes(filePath);

    ByteArrayContent byteContent = new ByteArrayContent(fileData);

    byteContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");

    form.Add(byteContent, "file", Path.GetFileName(filePath));

    var result = await httpClient.PostAsync("/api/accounts/cease/bulk", form);
}

我到达控制器,但收到的 csvFile 为空。

ApiClient.HttpClient 是我们自己的客户端,但我不介意使用通用客户端。

我不得不说我们的 httpClient“PostAsync”收到了 HttpContent。

第二次尝试:

var httpClient = ApiClient.HttpClient;

var fileContent = new ByteArrayContent(ReadFully(file));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
    FileName = "CeaseBulkAccount.csv"
};

var response = await httpClient.PostAsync("/api/accounts/cease/bulk", fileContent, ct);

public static byte[] ReadFully(Stream input)
{
    byte[] buffer = new byte[16 * 1024];
    using (MemoryStream ms = new MemoryStream())
    {
        int read;
        while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        {
            ms.Write(buffer, 0, read);
        }
        return ms.ToArray();
    }
}

再次,csvFile 为空。

我们的 PostAsync:

//
// Summary:
//     Send a POST request with a cancellation token as an asynchronous operation.
//
// Parameters:
//   requestUri:
//     The Uri the request is sent to.
//
//   content:
//     The HTTP request content sent to the server.
//
//   cancellationToken:
//     A cancellation token that can be used by other objects or threads to receive
//     notice of cancellation.
//
// Returns:
//     The task object representing the asynchronous operation.
//
// Exceptions:
//   T:System.InvalidOperationException:
//     The requestUri must be an absolute URI or System.Net.Http.HttpClient.BaseAddress
//     must be set.
//
//   T:System.Net.Http.HttpRequestException:
//     The request failed due to an underlying issue such as network connectivity, DNS
//     failure, server certificate validation or timeout.
//
//   T:System.Threading.Tasks.TaskCanceledException:
//     .NET Core and .NET 5 and later only: The request failed due to timeout.
//
//   T:System.UriFormatException:
//     The provided request URI is not valid relative or absolute URI.
public Task<HttpResponseMessage> PostAsync([StringSyntax("Uri")] string? requestUri, HttpContent? content, CancellationToken cancellationToken);
c# post mocking xunit iformfile
1个回答
0
投票

传递给

form.Add
的名称必须与控制器的action方法中的名称匹配;
[FromForm] IFormFile csvFile

因为那个是

csvFile
,所以你必须添加如下文件。

form.Add(byteContent, "csvFile", Path.GetFileName(filePath));

通过上述更改,您的第一次尝试效果很好。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.