Home > Software design >  How to write Testcases for an API that accepts an object that includes IFormFile typed fields in .NE
How to write Testcases for an API that accepts an object that includes IFormFile typed fields in .NE

Time:05-04

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);
  • Related