Модульное тестирование вложенных методов - PullRequest
2 голосов
/ 03 марта 2020

Хотя я понимаю, что при модульном тестировании метода очень важно высмеивать все его зависимости, но я все еще не понимаю, что происходит, когда метод вложен? Должен ли я издеваться только над зависимостями родительского метода, или я также высмеиваю зависимости от дочерних методов или я устанавливаю ожидания для вызовов к зависимому объекту и устанавливаю точные возвращаемые значения, чтобы я мог выполнить тест что я хочу?

Например, в приведенном ниже примере, если мы хотим провести модульное тестирование метода B, мы только высмеиваем IHttpClientFactory & ILogger или мы также устанавливаем возвращаемое значение метода в мы на самом деле ожидаем, потому что в противном случае, когда тестовый метод выполняется, он идет вперед и пытается выполнить метод C, где он терпит неудачу, потому что значение client после выполнения строки var client = _clientFactory.CreateClient() равно нулю?

using System.Net.Http;
...

public class classA
{
   private readonly IHttpClientFactory _clientFactory;
   private sting url = "...";
   private ILogger _log { get; set; }
   ...

   public classA(ILogger log, IHttpClientFactory clientFactory, ...)
   {
     _log = log;
     _clientFactory = clientFactory;
     ...
   }

   public string methodB(string inputB)
   {
      var varB = methodC(inputB);
      ...
      return ..;
   }

   public string methodC(string inputC)
   {
      ...
      var client = _clientFactory.CreateClient();
      client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
      HttpResponseMessage httpResponseMessage = await client.PostAsync(url, new StringContent(inputC, Encoding.UTF8, "application/json"));
      responJsonText = await httpResponseMessage.Content.ReadAsStringAsync();
      ...
      return ..;
   }

}

1 Ответ

1 голос
/ 03 марта 2020

Итак, у вас есть HTTP-клиент, высокоуровневый метод, который дает вам некоторые структурированные данные, и низкоуровневый метод, который возвращает вам содержимое ответа.

Эти вещи скорее искусство, чем жесткие правила, но в большинстве случаев я предпочитаю писать код, который может иметь весь его ввод / вывод, а затем имитировать или тестировать реализацию самого ввода / вывода. Таким образом, большая часть бизнес-логики c будет тестируемой.

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

Когда вы имитируете функциональность, наиболее распространенные вещи, которые вас интересуют, это проверка ввода метода или эмуляция его вывода ( или оба). Таким образом, в вашем макете вы не должны быть слишком обеспокоены фактической реализацией, так как вы не тестируете свой макетированный метод - вы тестируете все, что его вызывает.

Итак ... о вашем примере кода. Если вы пытаетесь протестировать MethodB, вам потребуется метод C, чтобы иметь тестовую реализацию - либо путем насмешки над HttpClient, на который он опирается, либо путем установки virtual и переопределения в тесте.

Примечание: повторно используйте HttpClient, сохраните его с классом

...