Search code examples
c#.netautomapper.net-5xunit

.NET 5 Class Library xUnit Tests failing when comparing objects from AutoMapper


I'm currently working out of a .NET 5 class library project with no Startup methods.

The idea behind what I'm, trying to achieve is that a developer can tap into this library and pass in an object. This object will run through the method, AutoMapper will grab the properties that align with the properties in the FirstDTO, then return a DTO that can be used throughout any other projects.

I'm relatively new to the AutoMapper bits and found this article here: How to configure Auto mapper in class library project?

I've liked this approach and have leveraged it to map a dynamic object to a DTO:

Configuration.cs

public static class Configuration
    {
        private static readonly Lazy<IMapper> Lazy = new Lazy<IMapper>(() =>
        {
            var config = new MapperConfiguration(cfg =>
            {
                cfg.ShouldMapProperty = p => p.GetMethod.IsPublic || p.GetMethod.IsAssembly;
                cfg.AddProfile<MappingProfile>();
            });

            IMapper mapper = config.CreateMapper();

            return mapper;
        });

        public static IMapper Mapper => Lazy.Value;
    }

Almost verbatim approach.

I have my MappingProfile.cs class:

    public class MappingProfile : Profile
    {
        public MappingProfile()
        {
            CreateMap<dynamic, FirstDTO>();
            CreateMap<dynamic, SecondDTO>();
        }
    }

When I call my base class I have the following method:

public class BaseLibraryClass : IBaseLibraryClass
    {
        public FirstDTO GetFirstObject(dynamic objectSentIn)
        {
            return Configuration.Mapper.Map<FirstDTO>(objectSentIn);
        }
    }

Which, in my though, should work.

Now when I write my xUnit unit tests, I'm having a failed Assert.Equal when comparing the FirstDTO with a built DTO:

        private readonly IBaseLibraryClass baseLibraryClass = new BaseLibraryClass();
        private readonly FirstDTOBuilder firstDTOBuilder = new FirstDTOBuilder();

        [Fact]
        public void TestSeparateObject()
        {
            // Arrange
            FirstDTO firstDTO = firstDTOBuilder.DefaultDTO().Build();

            // Act
            FirstDTO result = baseLibraryClass.GetFirstObject(firstDTO);

            // Assert
            Assert.Equal(firstDTO, result);
        }

What ends up happening when I debug this unit test, is that a DTO is built with the assigned properties via the Builder. It passes the DTO into GetFirstObject successfully with the populated properties, but when it hits the return, it returns a FirstDTO object type with properties that are all zeroed out, ultimately failing my unit test.

I feel like it's something glaringly obvious, but I cannot for the life of me figure out what's causing the properties to not map properly.

Any assistance would be greatly appreciated!


Solution

  • Automapper supports mapping from dynamic out of the box, no need to configure anything, so in your case removing profile from the configuration (or removing CreateMap's from the profile) should just work:

    public static class Configuration
    {
        private static readonly Lazy<IMapper> Lazy = new Lazy<IMapper>(() =>
        {
            var config = new MapperConfiguration(cfg =>
            {
                cfg.ShouldMapProperty = p => p.GetMethod.IsPublic || p.GetMethod.IsAssembly;
            });
    
            IMapper mapper = config.CreateMapper();
    
            return mapper;
        });
    
        public static IMapper Mapper => Lazy.Value;
    }