Base solution for your next web application
Open Closed

unit test failing for mapper not initialized #5065


User avatar
0
OriAssurant created

I am using ITypeConvertor in the WebAPI project of Majestic. I had to add it as a dependency in the WebAPIModule class. Configuration.Modules.AbpAutoMapper().Configurators.Add(mapper => { TrackerMapper.CreateMappings(mapper); });

Now, I am trying to write test cases for the classes written in WebAPI project. But, I am getting this error during test cases:

The mapper initializations in webApi aren’t invoked from test module, as it is throwing the following error: System.InvalidOperationException : Mapper not initialized. Call Initialize with appropriate configuration. If you are trying to use mapper instances through a container or otherwise, make sure you do not have any calls to the static Mapper.Map methods, and if you're using ProjectTo or UseAsDataSource extension methods, make sure you pass in the appropriate IConfigurationProvider instance.

I have added the depends on attribute to the module as below. Which does not seem to help. Adding the tag DependsOn(typeof(MajesticWebApiModule) in TestModule class

Will appreciate inputs on why I am not able to using ITypeConvertor in the Test project.


10 Answer(s)
  • User Avatar
    0
    aaron created
    Support Team

    Show how you inject and use the mapper.

  • User Avatar
    0
    OriAssurant created

    This is the mapper class I have.

    using Abp.AutoMapper; using Abp.Modules; using AutoMapper; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;

    namespace WebApi.TrackerService {

    public static class TrackerMapper
    {
        private static volatile bool _mappedBefore;
        private static readonly object SyncObj = new object();
    
        public static void CreateMappings(IMapperConfigurationExpression mapper)
        {
            lock (SyncObj)
            {
                if (_mappedBefore)
                {
                    return;
                }
    
                CreateMappingsInternal(mapper);
    
                _mappedBefore = true;
            }
        }
    
        private static void CreateMappingsInternal(IMapperConfigurationExpression mapper)
        {
            mapper.CreateMap<Source, Destination>().ConvertUsing<TrackerTypeConverter>();            
           
        }
    
    }
    
    #region Mapping source to destination 
    
    public class TrackerTypeConverter : ITypeConverter<Source, Destination>
    {
    
        public Destination Convert(Source source, Destination destination, ResolutionContext context)
        {
    
    
            return
                    new Destination
                    {
                       //Transforming/mapping source to Destination
                    };
        }
    
       
    
    }
    #endregion
    

    }

    I'm initializing CreateMappings from WebApiModule Initialize method as below: //Adding custom AutoMapper mappings Configuration.Modules.AbpAutoMapper().Configurators.Add(mapper => { TrackerMapper.CreateMappings(mapper); });

    Invoking/using the mappings as below: var transformedRequest = Mapper.Map<Source, Destination>(request);

    This works fine as a webApi project. But when I write my test cases, the mappings from my mapper class are not getting initialized.

    In my test project, I added the attribute DependsOn[TypeOf(WebApiModule)] in TestModule class, but it doesn't seem to initialize the mappings from WebApiModule.

    Thank you for your response in advance :) I greatly appreciate it.

  • User Avatar
    0
    aaron created
    Support Team

    Are you using the static Mapper? Inject IObjectMapper instead.

  • User Avatar
    0
    OriAssurant created

    Does IObjectMapper support mapping of an object of one type to an object of an entirely different type? Why is it that the mappings from WebApiModule not initialized from TestModule class when I use DependsOn attribute?

  • User Avatar
    0
    aaron created
    Support Team

    Does IObjectMapper support mapping of an object of one type to an object of an entirely different type?

    Yes. Abp.AutoMapper package implements IObjectMapper by using AutoMapper's IMapper internally.

    Why is it that the mappings from WebApiModule not initialized from TestModule class when I use DependsOn attribute?

    Static mapper is disabled in AbpZeroTemplateTestModule.

  • User Avatar
    0
    OriAssurant created

    Where can I override this to enable static mapper for my test module?

  • User Avatar
    0
    aaron created
    Support Team

    You shouldn't.

  • User Avatar
    0
    OriAssurant created

    So, I took your suggestion to inject IObjectMapper to invoke the map as below: var transformedObject = _objectMapper.Map<Destination>(source);

    It failed with the following error:

    Mapper not initialized. Call Initialize with appropriate configuration. If you are trying to use mapper instances through a container or otherwise, make sure you do not have any calls to the static Mapper.Map methods, and if you're using ProjectTo or UseAsDataSource extension methods, make sure you pass in the appropriate IConfigurationProvider instance.

    And I have removed all references to static Mapper.Map and replaced them with IObjectMapper reference.

  • User Avatar
    0
    OriAssurant created

    So, I fixed the mapper initializing issue using IObjectMapper. However, the mappings are not being invoked, because it is returning null after the objectMapper.Map<>().

    This is what I have in PreInitialize of webApiModule: //Adding custom AutoMapper mappings Configuration.Modules.AbpAutoMapper().Configurators.Add(mapper => { TrackerMapper.CreateMappings(mapper); });

    Is it because I'm configuring mappings in WebApiModule?

  • User Avatar
    0
    alper created
    Support Team

    you have to done something wrong. Check out the existing code in application services; For example below code uses the ObjectMapper which is defined in application service base.

    public async Task<FileDto> GetUsersToExcel()
            {
                var users = await UserManager.Users.ToListAsync();
                var userListDtos = ObjectMapper.Map<List<UserListDto>>(users);
                await FillRoleNames(userListDtos);
                return _userListExcelExporter.ExportToFile(userListDtos);
            }