Register AutoMapper in XUnit Unit Tests in .Net Core 2.1

Viewed 1495

I'm getting a

"System.InvalidOperationException : Mapper already initialized. You must call Initialize once per application domain/process."

error when trying to register AutoMapper in my Unit test classes using the XUnit test framework.

I have an application with 3 layers (Presentation - Business - Data). Both the Business layer and the Presentation layer have their own AutoMapper Profile classes which are registered within a class called on Startup.

Business:

public class AutoMapperBusinessProfile : Profile
{
    public AutoMapperBusinessProfile()
    {
        CreateMap<WeatherEntity, WeatherModel>()
            .ForMember(x => x.Location, y => y.MapFrom(z => z.Name))
            .ForMember(x => x.Temperature, y => y.MapFrom(z => z.Main.Temp))

            // Here be mappings
            ...
    }
}

Presentation:

public class AutoMapperPresentationProfile : Profile
{
    public void RegisterMaps()
    {
        CreateMap<WeatherModel, MainViewModel>()
            .ForMember(dest => dest.TemperatureUom, x => x.MapFrom(src => src.TemperatureUom.ToString()));

        CreateMap<TrafficModel, MainViewModel>()
            .ConvertUsing<TrafficModelConverter>();

        // More mappings
        ...
    }
}

Startup:

public static class AutoMapperConfiguration
{
    public static void RegisterAutoMapper()
    {
        Mapper.Initialize(cfg =>
        {
            cfg.AddProfile<AutoMapperBusinessProfile>();
            cfg.AddProfile<AutoMapperPresentationProfile>();
        });
    }
}

I can run the application just fine, all mapping are correct. However; when trying to run unit tests on my code, I at first got null reference errors on the mapping parts. Adding code to reset and instantiate the Profile in the constructors allowed a single unit test class to run right.

public WeatherBusinessTests()
{
    _service = new WeatherService();

    // Initialize AutoMapper in test class
    Mapper.Reset();
    Mapper.Initialize(cfg => cfg.AddProfile<AutoMapperBusinessProfile>());
}

However, when running multiple test classes all using the Mapper.Reset() method I get the following error:

System.InvalidOperationException : Mapper already initialized. You must call Initialize once per application domain/process.

Running a single test class produces expected results. How can I register Automapper correctly so all my tests can run alongside each other and have the mappings information they need?

// Calling AutoMapper in code
public TModel MapFromEntity(TEntity entity)
{
   var model = Mapper.Map<TModel>(entity);
   return model;
}
1 Answers

I believe this part has problem, where you used RegisterMaps methods instead of constructor AutoMapperPresentationProfile()

public class AutoMapperPresentationProfile : Profile
{
    public void RegisterMaps()
    {
        CreateMap<WeatherModel, MainViewModel>()
            .ForMember(dest => dest.TemperatureUom, x => x.MapFrom(src => src.TemperatureUom.ToString()));

        CreateMap<TrafficModel, MainViewModel>()
            .ConvertUsing<TrafficModelConverter>();

        // More mappings
        ...
    }
}

Convert it to

public class AutoMapperPresentationProfile : Profile
{
    public void AutoMapperPresentationProfile ()
    {
        CreateMap<WeatherModel, MainViewModel>()
            .ForMember(dest => dest.TemperatureUom, x => x.MapFrom(src => src.TemperatureUom.ToString()));

        CreateMap<TrafficModel, MainViewModel>()
            .ConvertUsing<TrafficModelConverter>();

        // More mappings
        ...
    }
}
Related