Вопрос

Как люди подходят к издевательству над TcpClient (или такими вещами, как TcpClient)?

У меня есть сервис, который принимает TcpClient.Должен ли я обернуть это во что-то другое, более издевательское?Как мне следует подойти к этому?

Это было полезно?

Решение

При переходе к макетным классам, которые не подходят для тестирования (т.е.запечатанный / не реализующий какой-либо интерфейс / методы не являются виртуальными), вы, вероятно, захотите использовать Адаптер шаблон проектирования.

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

public interface ITcpClient
{
   Stream GetStream(); 
   // Anything you need here       
}
public class TcpClientAdapter: ITcpClient
{
   private TcpClient wrappedClient;
   public TcpClientAdapter(TcpClient client)
   {
    wrappedClient = client;
   }

   public Stream GetStream()
   {
     return wrappedClient.GetStream();
   }
}

Другие советы

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

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

   [Test]
    public void TestInput(){

       NetworkInputSource mockInput = mocks.CreateMock<NetworkInputSource>();
       Consumer c = new Consumer(mockInput);

       c.ReadAll();
    //   c.Read();
    //   c.ReadLine();

    }

    public class TcpClientAdapter : NetworkInputSource
    {
       private TcpClient _client;
       public string ReadAll()
       { 
           return new StreamReader(_tcpClient.GetStream()).ReadToEnd();
       }

       public string Read() { ... }
       public string ReadLine() { ... }
    }

    public interface NetworkInputSource
    {
       public string ReadAll(); 
       public string Read();
       public string ReadLine();
    }

Эта реализация полностью отделит вас от деталей, связанных с Tcp (если это является целью разработки), и вы даже можете передавать тестовые входные данные из жестко закодированного набора значений или тестового входного файла.Очень удобно, если вы находитесь на пути к длительному тестированию своего кода.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top