Как провести модульное тестирование сетевых подключений?

Я хочу протестировать код ниже. Я работал с MSTest и пытался изучить Microsoft Moles и RhinoMocks. Но я не мог заставить ни одного из них помочь мне. Я знаю, что могу кардинально изменить код, чтобы использовать интерфейсы, которые сделают его более тестируемым, но для этого мне потребуется кодировать интерфейсы и реализации, инкапсулирующие TcpClient, NetworkStream, StreamWriter и StreamReader.

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

using (TcpClient tcpClient = new TcpClient(hostName, port))
using (NetworkStream stream = tcpClient.GetStream())
using (StreamWriter writer = new StreamWriter(stream))
using (StreamReader reader = new StreamReader(stream))
{
    writer.AutoFlush = true;
    writer.Write(message);
    return reader.ReadLine();
}

person Jader Dias    schedule 16.12.2011    source источник
comment
Некоторые вещи просто не стоит пытаться тестировать. Если бы вы издевались над частями, которые использует этот метод, вы, по сути, проверяли бы установщик свойств, вызов метода writer и вызов метода reader. Здесь не так много поведения, и это не очень интересно для тестирования. Теперь было бы интересно протестировать классы, которые используют этот метод, поэтому я бы полностью реализовал этот класс как интерфейс и тестировал компоненты, которые вызывают его.   -  person Merlyn Morgan-Graham    schedule 16.12.2011


Ответы (1)


Будь проще.

Абстрагируйте сетевой уровень. Обычно я использую интерфейс с именем что-то вроде INetworkChannel, который выглядит примерно так:

public interface INetworkChannel : IDisposable
{
    void Connect(IPEndPoint remoteEndPoint);
    void Send(byte[] buffer, int offset, int count);

    public event EventHandler Disconnected;
    public event EventHandler<ReceivedEventArgs> Received;
}

Это упрощает тестирование всего, и вы можете создать класс SecureNetworkChannel, который использует SslStream или FastNetworkChannel, который использует новые асинхронные методы.

Такие детали, как используемый поток или использование TcpClient или Socket, не должны иметь значения для остальной части приложения.

Изменить

Тестировать реализацию INetworkingChannel тоже легко, так как теперь у вас есть класс с очень четкой ответственностью. Я создаю соединение со своими реализациями, чтобы проверить их. Пусть TcpListener прослушивает порт 0, чтобы ОС могла назначить свободный порт.

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

person jgauffin    schedule 16.12.2011
comment
+1; Если бы мне пришлось издеваться над такими вещами, я бы определенно хотел упрощенный интерфейс для множества задействованных классов. В основном шаблон Facade (как вы сделали здесь). Мне нравится дизайн этого интерфейса, потому что для его реализации потребуется очень мало смелости, и за ним практически не будет пользовательской логики приложения. Меня беспокоит только то, что это не IDisposible. Должно ли это быть? - person Merlyn Morgan-Graham; 16.12.2011
comment
@MerlynMorgan-Graham: Вы правы. Сокеты всегда должны быть утилизированы, особенно на серверах. И метод Close на самом деле не нужен, поскольку объекты Socket нельзя использовать повторно. - person jgauffin; 16.12.2011
comment
Да, очень хорошее упрощение! - person sll; 16.12.2011