【问题标题】:How to unit test client network code?如何对客户端网络代码进行单元测试?
【发布时间】:2011-03-01 16:13:30
【问题描述】:

我正在编写一段网络代码,它侦听 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.");
}

我应该如何尝试测试这种东西?

谢谢,

詹姆斯

【问题讨论】:

    标签: c# multithreading unit-testing client-server


    【解决方案1】:

    首先,这不是一个严格的“单元测试”;您的测试取决于具有副作用的架构层,在这种情况下传输网络数据包。这更像是一个集成测试。

    也就是说,正如托尼所说,您的单元测试可以休眠一定数量的毫秒。您还可以查看是否可以获得后台工作人员的句柄,并加入它,这将导致您的单元测试等待后台工作人员完成所需的时间。

    【讨论】:

      【解决方案2】:

      您可以等待一些超时时间,然后运行断言,因此:

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

      其中TIMEOUT 是您要等待的毫秒数。

      【讨论】:

      • 最初(当我直接从后台工作人员调用事件时)我使用的是这样的超时,效果很好。但是,从后台工作人员调用事件意味着处理程序也在工作线程上执行,导致 UI 层出现各种问题,因此我更改了代码以通过调度在主线程上引发事件,这似乎打破了超时方法在测试中。
      【解决方案3】:

      您可以使用一些超时,但与往常一样,超时应该持续多长时间才能确保您的测试始终通过,但仍然不会让您的测试减慢太多?

      我会简单地分开测试解析代码。这可能是您遇到最多错误的地方,也是您最需要单元测试的地方。而且测试很简单!

      然后,对于正在侦听套接字的代码...好吧,您可能会在这里遇到错误...但是如果它只是将数据分派给函数/类,我不确定您是否真的需要对其进行测试。而且,如果您想真正彻底,例如,如果客户端和服务器之间的连接丢失,您将如何对您的类进行单元测试以确保其表现良好?

      【讨论】:

        【解决方案4】:

        在我们的单元测试中,我们使用 .NET 4 的并行化库。你可以说:

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

        框架会负责将这些操作生成为不同的线程,在适合您正在处理的特定进程的多个线程中执行它们,然后将它们连接起来,以便下一条指令在它们之前不会执行都完成了。

        但是,您似乎无法直接访问该线程。相反,您希望等到给定的回调方法被调用。您可以使用 AutoResetEvent 或 ManualResetEvent 来完成此操作。

        见Unit testing asynchronous function

        【讨论】:

        • 谢谢,看起来很有趣。我会玩一下,看看我的进展如何。
        猜你喜欢
        • 2011-04-25
        • 1970-01-01
        • 2016-03-09
        • 1970-01-01
        • 1970-01-01
        • 2012-08-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多