Как выполнить модульное тестирование кода сети клиента? - PullRequest
4 голосов
/ 01 марта 2011

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

Класс адаптера:

public class NetworkAdapter : NetworkAdapterBase //NetworkAdapterBase is just an abstract base class with event definitions and protected Raise... methods.
{
    //Fields removed for brevity.

    public NetworkAdapter(TcpClient tcpClient)
    {
        _tcpConnection = tcpClient;

        //Hook up event handlers for background worker.
        NetworkWorker.DoWork += NetworkWorker_DoWork;

        if (IsConnected)
        {
            //Start up background worker.
            NetworkWorker.RunWorkerAsync();
        }
    }

    private void NetworkWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        while (IsConnected)
        {
            //Listen for incoming data, parse, raise events...
        }
    }
}

Попытка проверки кода:

[TestMethod]
public void _processes_network_data()
{
    bool newConfigurationReceived = false;

    var adapter = new NetworkAdapter(TestClient); //TestClient is just a TcpClient that is set up in a [TestInitialize] method.

    adapter.ConfigurationDataReceived += (sender, config) =>
    {
        newConfigurationReceived = true;
    };

    //Send fake byte packets to TestClient.

    Assert.IsTrue(newConfigurationReceived, "Results: Event not raised.");
}

Как мне попытаться протестировать такого рода вещи?

Спасибо,

Джеймс

Ответы [ 4 ]

6 голосов
/ 01 марта 2011

Ну, во-первых, это не строгий «модульный тест»; Ваш тест зависит от уровней архитектуры, которые имеют побочные эффекты, в данном случае передающие сетевые пакеты. Это скорее интеграционный тест.

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

2 голосов
/ 01 марта 2011

В наших модульных тестах мы используем библиотеку распараллеливания .NET 4.Вы можете сказать:

Parallel.Invoke(() => Dosomething(arguments), () => DosomethingElse(arguments));

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

Однако, похоже, у вас нет прямого доступа к потоку.Вместо этого вы хотите подождать, пока не будет вызван данный метод обратного вызова.Для этого вы можете использовать AutoResetEvent или ManualResetEvent.

См. Модульное тестирование асинхронной функции

2 голосов
/ 01 марта 2011

Вы можете использовать какое-то время ожидания, но, как всегда, какой продолжительностью должно быть время ожидания, чтобы убедиться, что ваш тест всегда будет проходить, но все равно не будет слишком сильно замедлять ваши тесты?Разбор кода на части.Это, вероятно, где вы будете иметь наибольшее количество ошибок, и где вам больше всего нужны юнит-тесты.И это просто проверить!

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

2 голосов
/ 01 марта 2011

Вы можете подождать некоторое время ожидания, а затем выполнить утверждение, таким образом:

//Send fake byte packets to TestClient
Thread.Sleep(TIMEOUT);
Assert.IsTrue(newConfigurationReceived, "Results: Event not raised.");

Где TIMEOUT - это количество миллисекунд, которое вы хотите подождать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...