集成测试 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,它看起来像下面这样。
希望本文能帮助您解决问题。
我在尝试为我的 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,它看起来像下面这样。
希望本文能帮助您解决问题。