skip to Main Content

I have 2 classes to map:

public class Note
    {
        public Guid UserId { get; set; }
        public Guid Id { get; set; }
        public string Title { get; set; }
        public string Body { get; set; }
        public DateTime CreationDate { get; set; }
        public DateTime EditDate { get; set; }
    }
public class NoteDetailsVm : IMapWith<Note>
    {
        public Guid Id { get; set; }
        public string Title { get; set; }
        public string Body { get; set; }
        public DateTime CreationDate { get; set; }
        public DateTime EditDate { get; set; }

        public void Mapping(Profile profile)
        {
            profile.CreateMap<Note, NoteDetailsVm>();
        }
    }

Here is the mapping profile and the mapping interface:

public class AssemblyMappingProfile : Profile
    {
        public AssemblyMappingProfile(Assembly assembly) =>
            ApplyMappingsFromAssembly(assembly);

        private void ApplyMappingsFromAssembly(Assembly assembly)
        {
            var types = (from t in assembly.GetExportedTypes()
                        where t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMapWith<>))  
                        select t).ToList();

            foreach (var type in types)
            {
                var instance = Activator.CreateInstance(type);
                var methodInfo = type.GetMethod("Mapping");
                methodInfo?.Invoke(instance, new object[] { this });
            }
        }
    }
public interface IMapWith<T>
    {
        void Mapping(Profile profile) =>
            profile.CreateMap(typeof(T), GetType());
    }

I use this method to handle requests and get the viewmodel:

public async Task<NoteDetailsVm> Handle(GetNoteDetailsQuery request, CancellationToken cancellationToken)
        {
            var entity = await _dbContext.Notes.FirstOrDefaultAsync(note => note.Id == request.Id, cancellationToken);

            if (entity == null || entity.UserId != request.UserId)
            {
                throw new NotFoundException(nameof(Note), request.Id);
            }

            return _mapper.Map<NoteDetailsVm>(entity);
        }

So when I run the tests, I get such error though I have the necessary mappings:

AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping.

AutoMapper.AutoMapperMappingException
Missing type map configuration or unsupported mapping.

Mapping types:
Note -> NoteDetailsVm
Notes.Domain.Note -> Notes.Application.Notes.Queries.GetNoteDetails.NoteDetailsVm
   at lambda_method259(Closure , Object , NoteDetailsVm , ResolutionContext )
   at Notes.Application.Notes.Queries.GetNoteDetails.GetNoteDetailsQueryHandler.Handle(GetNoteDetailsQuery request, CancellationToken cancellationToken)

Why isn’t the mapping working and how can I fix this?

2

Answers


  1. Chosen as BEST ANSWER

    Ok, I've managed to solve the problem, it had nothing to do with the code above. Just passed the wrong assembly to the profile constructor


  2. You most probably don’t handle initialization in your tests. Check this guide here: https://www.thecodebuzz.com/unit-test-mock-automapper-asp-net-core-imapper/

    The essence of it are these lines of code:

                if (_mapper == null)
                {
                    var mappingConfig = new MapperConfiguration(mc =>
                    {
                        mc.AddProfile(new SourceMappingProfile());
                    });
                    IMapper mapper = mappingConfig.CreateMapper();
                    _mapper = mapper;
                }
    

    They make sure there is an instance of the automapper that is properly initialized with the correct profile.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search