集成测试 multipart/form-data c#

Integration Testing multipart/form-data c#

我在尝试为我的 post 调用创建集成测试时遇到问题,该调用接受一个视图模型,该视图模型具有其他值,一个 IFormFile,它使这个调用从 application/json 到 multipart/form-data

我的集成设置class

protected static IFormFile GetFormFile()
        {
            byte[] bytes = Encoding.UTF8.GetBytes("test;test;");

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

            return file;
        } 

我的测试方法

public async Task CreateAsync_ShouldReturnId()
        {
            //Arrange
            using var content = new MultipartFormDataContent();
            var stringContent = new StringContent(
                JsonConvert.SerializeObject(new CreateArticleViewmodel
                {
                    Title = "viewModel.Title",
                    SmallParagraph = "viewModel.SmallParagraph",
                    Url = "viewModel.Url",
                    Image = GetFormFile()
                }),
                Encoding.UTF8,
                "application/json");
            stringContent.Headers.Add("Content-Disposition", "form-data; name=\"json\"");
            content.Add(stringContent, "json");

            //Act
            var response = await httpClient.PostAsync($"{Url}", content);
            //Assert
            response.StatusCode.ShouldBe(HttpStatusCode.OK);
            int id = int.Parse(await response.Content.ReadAsStringAsync());
            id.ShouldBeGreaterThan(0);
        }

我的控制器方法

[HttpPost]
        public async Task<IActionResult> CreateArticleAsync([FromForm] CreateArticleViewmodel viewModel)
        {

            var id = await _service.CreateAsync(viewModel).ConfigureAwait(false);
            if (id > 0)
                return Ok(id);
            return BadRequest();
        }

它在没有进入方法内部的情况下抛出 BadRequest。

您在代码中将请求内容发布到 API 的方式不正确。

当 API 期望请求有效载荷中有 FileInfo 时,发布 JSON 内容永远不会起作用。您需要将负载作为 MultipartFormData 而不是 JSON.

发送

考虑以下示例。

这是一个 API 端点,它期望将其中的 FileInfo 作为有效载荷进行建模。

[HttpPost]
public IActionResult Upload([FromForm] MyData myData)
{
    if (myData.File != null)
    {
        return Ok("File received");
    }
    else
    {
        return BadRequest("File no provided");
    }
}

public class MyData
{
    public int Id { get; set; }
    public string Title { get; set; }
    // Below property is used for getting file from client to the server.
    public IFormFile File { get; set; }
}

这与您的 API 几乎相同。

以下是使用文件和其他模型属性调用上述 API 的客户端代码。

var apiURL = "http://localhost:50492/home/upload";
const string filename = "D:\samplefile.docx";

HttpClient _client = new HttpClient();

// Instead of JSON body, multipart form data will be sent as request body.
var httpContent = new MultipartFormDataContent();
var fileContent = new ByteArrayContent(File.ReadAllBytes(filename));
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");

// Add File property with file content
httpContent.Add(fileContent, "file", filename);

// Add id property with its value
httpContent.Add(new StringContent("789"), "id");

// Add title property with its value.
httpContent.Add(new StringContent("Some title value"), "title");

// send POST request.
var response = await _client.PostAsync(apiURL, httpContent);
response.EnsureSuccessStatusCode();
var responseContent = await response.Content.ReadAsStringAsync();

// output the response content to the console.
Console.WriteLine(responseContent);

客户端代码 运行来自控制台应用程序。因此,当我 运行 这样做时,期望在控制台中收到 File received 消息,而我收到了该消息。

以下是调试时API端模型内容的屏幕截图。

如果我从邮递员那里调用这个 API,它看起来像下面这样。

希望本文能帮助您解决问题。