2017-02-14 3 views
0

Я обновляю свои знания об API Automapper.Инъекция и/или насмешка Automapper: зачем?

Изучая интерфейс IMapper, я нашел несколько сообщений об инъекции зависимостей и Automapper, например. this и this (они относятся к .NET Core, но это не имеет значения в контексте вопроса).

Предполагая, что типичное использование картографами как Automapper является:

public class Person 
{ 
    // person properties here 
} 

public class PersonDto 
{ 
    // person DTO properties here 
} 

public class SomeApi 
{ 
    // other code here 

    public PersonDto FindByName(string name) 
    { 
     var person = dbContext.People.FirstOrDefault(_ => _.Name == name); 

     // mapper is IMapper 
     return mapper.Map<PersonDto>(person); 
    } 
} 

почему мы хотим внедрить и/или макет IMapper?

Я понимаю, зачем вводить такие вещи, как dbContext, может быть полезно - при написании модульного теста вы должны как-то настроить тестовую среду, чтобы изолировать тестовый код от внешнего мира.

Но какой смысл для картографа?

Я имею в виду, отображение является частью логики метода. Это не «внешний мир». Это то, на что был написан метод, и это то, что нужно протестировать, но не издеваться.

Если я переписать FindByName без использования Automapper, код будет выглядеть следующим образом:

public PersonDto FindByName(string name) 
    { 
     var person = dbContext.People.FirstOrDefault(_ => _.Name == name); 

     if (person == null) 
      return null; 

     return new PersonDto 
     { 
      Name = person.Name, 

      // etc 
     }; 
    } 

Итак, что же мы инъекционный/насмешливый здесь? Операторы присваивания? Шутки в сторону?

Он выглядит как инъекция зависимостей для инъекций зависимостей без какой-либо выгоды.

Я что-то не хватает? Возможно, бывают случаи, когда инъекция/издевка Automapper действительно полезна (меня интересуют случаи, которые можно найти на практике, а не в теоретических)?

+0

Я согласен. У меня одинаковое представление: сопоставление - это внутренние детали метода, а в качестве клиента мне не нужно заботиться о том, выполняет ли метод ручное сопоставление или использует AutoMapper. В этом случае я считаю, что IMapper является чрезмерной абстракцией. –

ответ

2

Распаковка это на два вопроса:

  • Почему вы инъекционные IMapper?
  • Зачем вы издевались над IMapper?

Для первого вопроса я бы ввел IMapper в случае, если одному из расширений отображения нужна зависимость. Например, если вы используете пользовательские или ITypeConverter, который использует DbContext, вы должны убедиться, что в комплект поставки входит DbContext. Если вы настроили свой контейнер для создания экземпляра Mapper с заводским методом, то в расширениях используется обратный вызов фабричного метода для вашего контейнера.

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

Для второго вопроса я никогда не буду издеваться над IMapper в любом виде теста. Это как насмешка над JSON.net или StringBuilder, не так много.

+0

Спасибо большое, Джимми. Теперь это намного яснее. Итак, есть только один случай: вам нужно как-то расширить конфигурацию Automapper, используя 'IValueResolver' или' ITypeConverter'. Если вам это не нужно, вполне нормально создавать экземпляры mapper (или использовать статический API). Правильно? – Dennis

+0

Да, это так! –

0

Ну, по этой же причине: выполнить чистый единичный тест. Давайте рассмотрим код, который вы имеете в вашем вопросе и изменить его и добавить простой конструктор, как, например:

public class SomeApi 
{ 
    private IMapper mapper; 
    public SomeApi(IMapper mapper) 
    { 
     this.mapper = mapper; 
    } 
    // other code here 

    public PersonDto FindByName(string name) 
    { 
     var person = dbContext.People.FirstOrDefault(_ => _.Name == name); 

     // mapper is IMapper 
     return mapper.Map<PersonDto>(person); 
    } 
} 

Что делать, если я хотел написать модульный тест для FindByName, и я хотел дразнить IMapper, потому что я хочу тест быть чисто основанным на моем макете, а не на AutoMapper. Или что, если я не решил, что буду использовать AutoMapper, но любой тип, который реализует IMapper. Или, может быть, я не хочу, чтобы мой класс SomeApi был связан или зависел от AutoMapper.

Если класс SomeApi находится внутри сборки, ему не нужно знать об AutoMapper, и все, о чем он должен знать, это IMapper. Какую реализацию IMapper можно решить на Composition Root. Таким образом, если люди, которые используют ваш API, не любят AutoMapper, по какой-то причине могут использовать любой желающий.

В комментариях к этому ответу вы заявили:

1) Что вы тестирование, когда вы выбрасывая большая часть методы?

Я тестирую, работает ли код, который ищет в базе данных для человека по имени.

2) Впрыскивание IMapper, вы привносите зависимость от Automapper.

Нет, я не являюсь. Если ваш класс SomeApi не связан с IMapper AutoMapper, но это еще один интерфейс, который называется IMapper, но с меньшим количеством методов или с теми же методами, то это то, к чему вы связываетесь.

3) Вы когда-нибудь видели пользовательские реализации IMapper (я имею в виду, на практике)?

Нет, у меня его нет. Я тоже не видел компилятора, но они существуют. Я давно видел, что кто-то написал статью об эффективности AutoMapper (и других картперах) против ручного сопоставления, и я вижу, почему некоторые люди могут захотеть использовать свой собственный картограф. См. this.

Вопрос в том, почему это делается, и вот о чем я могу думать. Я утверждаю, что вы должны это делать? Точно нет.

+0

Всего несколько точек. 1) Сопоставление от объекта к DTO является частью логики метода. На самом деле, здесь нечего тестировать. Это то, для чего существует метод (см. Образец с байтовым отображением). Что вы испытываете, когда выбрасываете большую часть метода? 2) Инъекция «IMapper», вы вызываете зависимость от Automapper. Если вам действительно нужно принести настраиваемое сопоставление, вам нужно придумать свой «IMapper» и обернуть внутри него Automapper. 3) Вы когда-нибудь видели пользовательские реализации «IMapper» (я имею в виду, на практике)? – Dennis

+0

@ Деннис, пожалуйста, см. Мое редактирование. – CodingYoshi

Смежные вопросы