2008-09-29 7 views
8

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

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

ответ

22

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

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

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(); 
    } 
} 
+0

Это замечательно! Благодаря! – 2008-09-29 20:49:31

+0

+1 лучшее объяснение плюс хороший простой пример – Ahmad 2010-10-11 07:22:26

2

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

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

5

Я думаю @ 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 связанных деталей в целом (если это дизайн цель), и вы можете даже трубы в тестовом входе с жестким кодированным набором значений , или тестовый входной файл. Очень хорошо, если вы находитесь на пути к тестированию своего кода надолго.