Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to deserialize C# async OkResult from controller that uses mongodb

I’m trying to create xUnit using mock tests for my api that uses DataAccess layer for mongodb. But for some reason it just doesn’t parse okResult to Json or Bson. I definitely know that there is 2 values that I need from debugger: 2 Values to parse
My model is:

namespace DataAccess.Models;
[BsonIgnoreExtraElements]
public class CyberGood
{
    [BsonId]
    [BsonElement("id")]
    public ObjectId Id { get; set; }

    [BsonElement("name")]
    public string Name { get; set; }

    [BsonElement("description")]
    public string Description { get; set; }

    [BsonElement("insideOf")]
    public string? InsideOf { get; set; }

    [BsonElement("madeIn")]
    public string MadeIn { get; set; }

    [BsonElement("price")]
    public decimal Price { get; set; }

    [BsonElement("amount")]
    public int Amount { get; set; }
}

And my controller is:

    [Route("api/[controller]")]
    [ApiController]
    public class CyberGoodController : ControllerBase
    {
        private readonly ICyberGoodService _cyberGoodService;

        public CyberGoodController(ICyberGoodService cyberGoodService)
        {
            _cyberGoodService = cyberGoodService;
        }

        [HttpGet]
        public async Task<IActionResult> GetAllCyberGoodAsync()
        {
            try
            {
                var cyberGoods = await _cyberGoodService.GetAllCyberGoodAsync();
                return Ok(cyberGoods);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }

My test case:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

        [Fact]
        [Obsolete]
        public async Task GetAll_CyberGoods_ReturnsList()
        {
            //Arrange
            var mock = new Mock<ICyberGoodService>();
            mock.Setup(d => d.GetAllCyberGoodAsync()).ReturnsAsync(GetTestCyberGoods());
            var service = new CyberGoodController(mock.Object);
            var objectSerializer = new ObjectSerializer(type => ObjectSerializer.DefaultAllowedTypes(type) 
            || type.FullName.StartsWith("DataAccess") 
            || type.FullName.StartsWith("Microsoft.AspNetCore.Mvc.OkObjectResult")); 
            BsonSerializer.RegisterSerializer(objectSerializer);

            //Act
            IActionResult result = await service.GetAllCyberGoodAsync();
            var bsonRes = BsonSerializer.Deserialize<List<CyberGood>>(result.ToBson());

            //Assert
            Assert.Equal(GetTestCyberGoods().Count, bsonRes.Count);

        }

But instead of some test result it gives me this error:
Message: 
MongoDB.Bson.BsonSerializationException : An error occurred while serializing the Value property of class Microsoft.AspNetCore.Mvc.ObjectResult: Type System.Collections.Generic.List1[[DataAccess.Models.CyberGood, DataAccess, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] is not configured as an allowed type for this instance of ObjectSerializer. ---- MongoDB.Bson.BsonSerializationException : Type System.Collections.Generic.List1[[DataAccess.Models.CyberGood, DataAccess, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] is not configured as an allowed type for this instance of ObjectSerializer.

Stack Trace: 
BsonClassMapSerializer1.SerializeMember(BsonSerializationContext context, Object obj, BsonMemberMap memberMap) BsonClassMapSerializer1.SerializeClass(BsonSerializationContext context, BsonSerializationArgs args, TClass document)
BsonClassMapSerializer1.Serialize(BsonSerializationContext context, BsonSerializationArgs args, TClass value) IBsonSerializer.Serialize(BsonSerializationContext context, BsonSerializationArgs args, Object value) ObjectSerializer.SerializeDiscriminatedValue(BsonSerializationContext context, BsonSerializationArgs args, Object value, Type actualType) ObjectSerializer.Serialize(BsonSerializationContext context, BsonSerializationArgs args, Object value) DiscriminatedInterfaceSerializer1.Serialize(BsonSerializationContext context, BsonSerializationArgs args, TInterface value)
IBsonSerializer.Serialize(BsonSerializationContext context, BsonSerializationArgs args, Object value)
BsonExtensionMethods.ToBson(Object obj, Type nominalType, BsonBinaryWriterSettings writerSettings, IBsonSerializer serializer, Action1 configurator, BsonSerializationArgs args) BsonExtensionMethods.ToBson[TNominalType](TNominalType obj, IBsonSerializer1 serializer, BsonBinaryWriterSettings writerSettings, Action1 configurator, BsonSerializationArgs args) CyberGoodControllerTests.GetAll_CyberGoods_ReturnsList() line 30 --- End of stack trace from previous location --- ----- Inner Stack Trace ----- ObjectSerializer.SerializeDiscriminatedValue(BsonSerializationContext context, BsonSerializationArgs args, Object value, Type actualType) ObjectSerializer.Serialize(BsonSerializationContext context, BsonSerializationArgs args, Object value) IBsonSerializer.Serialize(BsonSerializationContext context, BsonSerializationArgs args, Object value) IBsonSerializerExtensions.Serialize(IBsonSerializer serializer, BsonSerializationContext context, Object value) BsonClassMapSerializer1.SerializeNormalMember(BsonSerializationContext context, Object obj, BsonMemberMap memberMap)
BsonClassMapSerializer`1.SerializeMember(BsonSerializationContext context, Object obj, BsonMemberMap memberMap)

>Solution :

Don’t think BsonSerializer can serialize/deserialize the value with IActionResult type.

Instead,

  1. Cast result as OkObjectResult type. And assert the okResult is not null to prove the action returns an OkObjectResult.

  2. Extract okResult.Value and cast it as List<CyberGood> type. And assert the bsonRes is not null to prove that the value is List<CyberGood> type.

  3. Lastly, you are able to perform the assertion for matching the counts.

IActionResult result = await service.GetAllCyberGoodAsync();
var okResult = result as OkObjectResult();

// Validate result returned as OkResult
Assert.NotNull(okResult);
var bsonRes = okResult.Value as List<CyberGood>;

// Assert bsonRes is List<CyberGood> type
Assert.NotNull(bsonRes);

// Assert
Assert.Equal(GetTestCyberGoods().Count, bsonRes.Count);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading