Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test client network code?

I'm working on a piece of networking code which listens to a TCP connection, parses the incoming data and raises the appropriate event. Naturally, to avoid blocking the rest of the application, the listening and parsing are performed in a background worker. When trying to unit test this code I run into the problem that, seeing as the network code has more work to do than the unit test, the unit test completes before the adapter has a chance to raise the event and so the test fails.

Adapter class:

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...
        }
    }
}

Attempted test code:

[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.");
}

How should I go about trying to test this sort of thing?

Thanks,

James

like image 409
Moonshield Avatar asked Dec 16 '22 16:12

Moonshield


2 Answers

Well, first, this is not a strict "unit test"; your test depends upon layers of architecture that have side effects, in this case transmitting network packets. This is more of an integration test.

That said, your unit test could sleep for a certain number of millis, as Tony said. You could also see if you can get a handle to the background worker, and Join on it, which will cause your unit test to wait as long as it takes for the background worker to finish.

like image 59
KeithS Avatar answered Dec 31 '22 04:12

KeithS


You could wait for some timeout period, then run the assertion, thusly:

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

Where TIMEOUT is the number of milliseconds you want to wait.

like image 42
Tony Casale Avatar answered Dec 31 '22 04:12

Tony Casale