Написание модульного теста для утилиты, которая потребляет RestClient - PullRequest
0 голосов
/ 17 октября 2018

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

// pseudo-code
public class HttpLog{
      private readonly string uri;
      private readonly RestClient client;

      public HttpLog(string uri){
          this.uri = uri;
          // notice the initialization of rest client
          this.client = new RestClient();
      }

     void write(object data){
         this.client.uri = this.uri + endpoint;
         this.client.postAsync(data);
     }           
}

Потребитель должен предоставить URI, и мы предоставили открытые методы записиоднако для регистрации данных мы не можем провести модульное тестирование нашего класса HttpLog, поскольку он инициализирует остальных клиентов.Мы не используем внедрение зависимостей, так как мы создаем утилиту.

Любая помощь будет с благодарностью о том, как провести рефакторинг или модульный тест. write() метод.

Мы можем придумать два метода

  • Перегрузка конструктора (что не является эффективным способом только для модульного тестирования)
  • превращение свойства клиента в общедоступное {get;set}, который также нарушает принцип ООП.

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

В ответах ниже указано использование конструкторапубличная перегрузка или создание свойства

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

Например, если вы используете RestClient или HttpClient, они не просят вас предоставить реализацию HTTP о том, как записывать данные, они просто просят вас URI и данные для публикации, что и является настоящей абстракцией для завершенияпользователь.

Пожалуйста, поправьте меня, если мои предположения неверны

Ответы [ 2 ]

0 голосов
/ 17 октября 2018

Мы не используем внедрение зависимостей, так как создаем утилиту.

Это не причина.Если вы используете зависимости и хотите правильно их протестировать, вы должны использовать внедрение зависимостей.Это не означает, что вы не можете предоставить реализацию по умолчанию для обычных пользователей.

Обеспечить перегрузку конструктора.Я понятия не имею, почему вы думаете, что это будет "неэффективно".

Пример:

public class HttpLog{
      private readonly string uri;
      private readonly RestClient client;

      public HttpLog(string uri) : this(uri, new RestClient()){
      }

      public HttpLog(string uri, RestClient restClient){
          this.uri = uri;
          // notice the initialization of rest client
          this.client = restClient;
      }

     void write(object data){
         this.client.uri = this.uri + endpoint;
         this.client.postAsync(data);
     }           
}
0 голосов
/ 17 октября 2018

Перво-наперво: что вы тестируете?Ваш метод или сама служба REST?

Поскольку вы говорите "мы не можем выполнить модульное тестирование нашего класса HttpLog" , я полагаю, вы пытаетесь протестировать свой класс.

Следовательно, вы должны протестировать его без службы REST (которая является внешней зависимостью).REST-клиент должен быть внедрен как зависимость, поэтому его можно легко смоделировать.

Мы не используем внедрение зависимости, поскольку мы создаем утилиту.

То естьнедопустимый аргумент для пропуска внедрения зависимостей.

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

  1. Перегрузка конструктора (которая являетсяне эффективный способ только для модульного тестирования)

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

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

сделать собственность клиента общедоступной {get;set}, который также нарушает принцип ООП.

Ваше второе предложение прямо доказывает, что вы готовы (и пытаетесь) внедрить зависимость .Вы просто пытаетесь внедрить его через общедоступное свойство вместо параметра конструктора.

Вы правы в том, что использование общедоступного свойства не является хорошим решением, так как оно открывает двери для других проблем.
Сравнительно, использование параметра конструктора обеспечивает те же функциональные возможности (публичный выбор клиента) безкомпрометация инкапсуляции (неспособность изменить клиента в течение срока жизни объекта).

Следовательно, ответом будет использовать внедрение зависимостей .

...