Имитация вызова AutoMapper Mapper.Map с использованием Moq

Как лучше всего настроить фиктивное ожидание для функции карты в AutoMapper.

Я извлекаю интерфейс IMapper, чтобы настроить ожидания для этого интерфейса. У моего маппера есть зависимости, поэтому я должен передать их мапперу.

Что происходит, когда я создаю 2 экземпляра своего класса картографа с 2 разными реализациями зависимостей? Я предполагаю, что оба картографа будут использовать один и тот же экземпляр зависимости, поскольку карта AutoMapper является статической. Или AutoMapper может даже выдать исключение, потому что я пытаюсь настроить две разные карты с одними и теми же объектами?

Каков наилучший способ решить эту проблему?

public interface IMapper {
    TTarget Map<TSource, TTarget>(TSource source);
    void ValidateMappingConfiguration();
}

public class MyMapper : IMapper {
    private readonly IMyService service;

    public MyMapper(IMyService service) {
        this.service = service
        Mapper.CreateMap<MyModelClass, MyDTO>()
            .ForMember(d => d.RelatedData, o => o.MapFrom(s =>
                service.getData(s.id).RelatedData))
    }

    public void ValidateMappingConfiguration() {
        Mapper.AssertConfigurationIsValid();
    }

    public TTarget Map<TSource, TTarget>(TSource source) {
        return Mapper.Map<TSource, TTarget>(source);
    }
}

person Alex Johansson    schedule 26.02.2010    source источник


Ответы (5)


Каков наилучший способ настроить ложное ожидание для функции карты в AutoMapper[?]

Вот один из способов:

var mapperMock = new Mock<IMapper>();
mapperMock.Setup(m => m.Map<Foo, Bar>(It.IsAny<Foo>())).Returns(new Bar());
person Mark Seemann    schedule 26.02.2010
comment
Просто небольшое дополнение. mapperMock.Setup(m => m.Map<Foo, Bar>(It.IsAny<Foo>())).Returns((Foo src) => new Bar(){ Value = src.Value}); - person John Nyingi; 05.03.2020

Вам не нужно имитировать AutoMapper, вы можете просто внедрить настоящий, как описано здесь:

var myProfile = new MyProfile();
var configuration = new MapperConfiguration(cfg => cfg.AddProfile(myProfile));
IMapper mapper = new Mapper(configuration);

Вы можете внедрить этот преобразователь в свои модульные тесты. Весь смысл использования таких инструментов, как AutoMapper, заключается в том, что вам не нужно писать много кода для сопоставления. Если вы издеваетесь над AutoMapper, вам придется это сделать.

person ataravati    schedule 16.11.2019
comment
Я все еще могу открыть его. - person ataravati; 25.03.2020
comment
Странный. Значит, мой провайдер блокирует сайт? Error 522 Ray ID: 5798fed7d802d24c • 2020-03-25 13:32:00 UTC Connection timed out Если бы вы могли как-то помочь мне просмотреть его, экспортировав его, возможно, в машину времени, это было бы здорово. - person SpiritBob; 25.03.2020
comment
Согласованный. Мок-маппер в каждой модели — это пустая трата времени, за исключением того, что вам нужно проверить правильность вашего профиля картографа. - person wtf512; 29.04.2020

http://richarddingwall.name/2009/05/07/mocking-out-automapper-with-dependency-injection/

Указывает на другой способ обработки зависимостей AutoMapper, который в основном заменит мою попытку извлечь мой собственный интерфейс IMapper. Вместо этого я попытаюсь использовать существующий IMappingEngine в качестве зависимости для своих классов, чтобы посмотреть, работает ли это.

person Alex Johansson    schedule 26.02.2010

Что вам нужно сделать, так это настроить AutoMapper следующим образом (StructureMap — это IoC). Затем вы можете сделать свои службы зависимыми от IMappingEngine. Оттуда издеваться над этим должно быть очень легко.

public class AutoMapperConfigurationRegistry : Registry
    {
        public AutoMapperConfigurationRegistry()
        {
            ForRequestedType<Configuration>()
                .CacheBy(InstanceScope.Singleton)
                .TheDefault.Is.OfConcreteType<Configuration>()
                .CtorDependency<IEnumerable<IObjectMapper>>().Is(expr => expr.ConstructedBy(MapperRegistry.AllMappers));

            ForRequestedType<ITypeMapFactory>().TheDefaultIsConcreteType<TypeMapFactory>();

            ForRequestedType<IConfigurationProvider>()
                .TheDefault.Is.ConstructedBy(ctx => ctx.GetInstance<Configuration>());

            ForRequestedType<IConfiguration>()
                .TheDefault.Is.ConstructedBy(ctx => ctx.GetInstance<Configuration>());
        }
    }
person epitka    schedule 21.04.2010

Причина, по которой вам нужно вызывать конфигурацию автосопоставления, заключается в том, что экземпляр UNIT Test case запускается вне основных файлов/конфигураций запуска приложения. Следовательно, конфигурация автоматического сопоставления должна быть вызвана и настроена до того, как начнут выполняться какие-либо модульные тесты. В идеале вы помещаете его в методы TestInitialize.

person littleinstein    schedule 01.09.2020