This is my controller code. Here it accepts UpdateMediaDto
object that contains IFormFile
data ( e.g. images and audios).
[HttpPut("words/{wordId}/medias/{id}")]
public async Task<ActionResult<WordMediaDto>> UpdateWordMedia(Guid wordId, Guid id, [FromForm] UpdateMediaDto mediaDto)
{
WordMedia? media = await _unitOfWork.WordMediaRepository.GetByIdAsync(id);
if (media == null) return NotFound();
if (wordId != media.WordId) return BadRequest("No Word present for this media");
var newMedia = _mediaFileMasterService.UpdateMedias(mediaDto);
//............
}
And this is my testcase
[Fact]
public async Task PUT_Media_with_UpdateMediaDto_results_WordMediaDto_success()
{
var ImagefileMock = new Mock<IFormFile>();
var content = System.Text.Encoding.UTF8.GetBytes("// byte[]....");
var ImagefileName = "sampleImage.jpg";
var ms = new MemoryStream();
var writer = new StreamWriter(ms);
writer.Write(content);
writer.Flush();
ms.Position = 0;
ImagefileMock.Setup(_ => _.OpenReadStream()).Returns(ms);
ImagefileMock.Setup(_ => _.FileName).Returns(ImagefileName);
ImagefileMock.Setup(_ => _.Length).Returns(ms.Length);
UpdateMediaDto mediaDto = new() {
Id = Guid.Parse("f1659b04-85a3-4969-7d20-08da081a9616"),
wordId=Guid.Parse("2caf24aa-4d37-4f64-aa91-4a605798c35b"),
PrimaryImage=ImagefileMock.Object,
SecondaryImage1 = ImagefileMock.Object };
HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(mediaDto), Encoding.UTF8);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data");
//Act
var response = await _httpClient.PutAsync("api/v1/admin/words/d9823bdd-0d11-42e5-a804-4d59d393d2bc/medias/f47136e3-754a-4f2b-b5cc-08da2d91a92e", httpContent);
//Assert
response.EnsureSuccessStatusCode();
}
But Here I can't serialize the object using SerializeObject
. when I execute this test case I get an error like
Newtonsoft.Json.JsonSerializationException : Self referencing loop detected for property 'Object' with type 'Castle.Proxies.IFormFileProxy'. Path 'PrimaryImage.Mock'.
How can I solve this problem... and is there any other ways to test API like this?
CodePudding user response:
The proxy created by MOQ is causing an issue with the serialization in this case.
Consider using an actual FormFile
instance which is derived from IFormFile
.
[Fact]
public async Task PUT_Media_with_UpdateMediaDto_results_WordMediaDto_success() {
//Setup mock file using a memory stream
string content = System.Text.Encoding.UTF8.GetBytes("// byte[]....");
string ImagefileName = "sampleImage.jpg";
MemoryStream ms = new MemoryStream();
StreamWriter writer = new StreamWriter(ms);
writer.Write(content);
writer.Flush();
ms.Position = 0;
//create FormFile with desired data
IFormFile ImagefileMock = new FormFile(ms, 0, ms.Length, "name_from_form", ImagefileName);
UpdateMediaDto mediaDto = new() {
Id = Guid.Parse("f1659b04-85a3-4969-7d20-08da081a9616"),
wordId=Guid.Parse("2caf24aa-4d37-4f64-aa91-4a605798c35b"),
PrimaryImage=ImagefileMock,
SecondaryImage1 = ImagefileMock
};
HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(mediaDto), Encoding.UTF8);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data");
//Act
var response = await _httpClient.PutAsync("api/v1/admin/words/d9823bdd-0d11-42e5-a804-4d59d393d2bc/medias/f47136e3-754a-4f2b-b5cc-08da2d91a92e", httpContent);
//Assert
response.EnsureSuccessStatusCode();
}
CodePudding user response:
It seems you need to use MultipartFormDataContent
to build your form and add parts. To Stream objects use StreamContent
.
var multiPartformData = new MultipartFormDataContent();
var streamContent = new StreamContent(ImagefileMock);
multiPartformData .Add(streamContent);