[英]Testing a .net core web api controller file upload using XUnit and AspNetCore.TestHost
I have this controller to upload files:我有这个 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");
}
I am trying to write a unit text using XUnit and the Microsoft.AspNetCore.TestHost and I can't figure out how to write the test for the file upload.我正在尝试使用 XUnit 和Microsoft.AspNetCore.TestHost编写单元文本,但我不知道如何编写文件上传测试。 Here is one test I'm using to get a badrequest:
这是我用来获取错误请求的一项测试:
[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);
}
This test is passing.这个测试通过了。 I have written all the other test for the GET methods without a problem, I just don't know how to do this test.
我已经为 GET 方法编写了所有其他测试,没有问题,我只是不知道如何进行此测试。 I was thinking I could have a test file on my local test machine to upload, I just don't know how to construct the POST.
我在想我可以在我的本地测试机器上上传一个测试文件,我只是不知道如何构建 POST。
Here is the my constructor for the Class:这是我的 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();
}
This creates the client I need to GET, POST, etc.这将创建我需要 GET、POST 等的客户端。
Here is the final solution to the problem.这是问题的最终解决方案。 Using the answer from @gpaoli and a little looking around I got this code to post and pass the test.
使用@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);
Couple of problems I had was adding the stringContent and making sure that the File, and string content was named correctly so the controller could map the values.我遇到的几个问题是添加 stringContent 并确保正确命名文件和字符串内容,以便 controller 可以 map 值。
Do you need make post similar this:您是否需要发布类似的帖子:
// 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.