c# - 单元测试心跳功能

标签 c# unit-testing nunit client-server integration-testing

我有一个基于 TCP 的客户端-服务器系统,用 C# 编码。我被要求添加双向心跳来发现网络中是否有任何元素卡住并且没有响应。

我通过从服务器向所有连接的客户端发送心跳并等待响应来解决了这个问题。如果响应未按时到达,则会出现超时;如果服务器在 2 秒内没有发送任何心跳(假设服务器被卡住),客户端也会出现超时。

一切都在内部发生,服务器和客户端都会公开任何事件(接收心跳、回复心跳,按照请求静默发生)

问题是..如何为这样的功能创建单元测试或集成测试?

注意:我在 Visual Studio、C#、.Net 4.6.1 中进行编码,使用 NUnit3 进行测试

简短的伪代码示例:

//we have one connector for each connected client
class connector{

    //if the echoReceived timer is not reseted on time it will complain
    Timer echoReceived = new Timer(200ms);
    //Another timer for sending beats
    Timer heartbeatSender = new Timer (1000ms);

    OnClientConnected(Client)
    {        
        echoReceived.elapsed += () => { ShowError("Client did not reply") };

        heartbeatSender.elapsed += () => {
            Send(client, new Message(Heartbeat));
            echoReceived.Enabled = true;
        });
        heartbeatSemder.isEnabled = true;
    }

    OnNewMessageFromClient(Client, message)
    {
        if(message is echoedHeartBeat)
        {
            echoReceived.Enabled= false;
            echoReceived.Reset();
        }        
    }

}

在客户端

class client 
{
     Timer ServerDeadTimeOut = new Timer (1000ms);

     OnStart()
     {
         serverDeadTimeOut.Elapsed += () => { ShowError("Server is dead"); };
         serverDeadTimeOut.isEnabled = true;
     }

     OnNewMessageFromServer(message)
     {
         if(message is HeartBeatMessage)
         {
             serverDeadTimeOut.Reset();
             Send(new HeartBeatEchoMessage);
         }
     }
}

最佳答案

我会选择单元测试,集成需要在两者之间建立某种连接,具体取决于实现,它可能更容易或更难。单元测试将简单地依赖于抽象。只需将接口(interface)注入(inject)连接器,并在单元测试中将它们替换为 Mock,以模拟您设计该类的场景。当然,您必须测试 Timer、Logger 和 ClientListener 的实际实现,但这就是单元测试的用途。

public class ConnectorTest
{
    private readonly Connector _connector;
    private readonly TimerMock _receiverMock;
    private readonly TimerMock _senderMock;
    private readonly LoggerMock _loggerMock;
    private readonly ClientListenerMock _listenerMock;

    public void Setup()
    {
        _listenerMock = new ClientListenerMock();
        _receiverMock = new TimerMock();
        _senderMock  = new TimerMock();
        _loggerMock = new LoggerMock();
        _connector = new Connector(_listenerMock, _receiverMock, _senderMock, _loggerMock)
    }

    public void HeartbeatSender_ShouldBeEnabled_OnceClientIsConnected()
    {
        _listenerMock.SimulateClientConnection();

        Assert.IsTrue(_senderMock.IsEnabled);
    }

    public void Error_ShouldBeLogged_WhenConnectedClientDidNotEchoed()
    {
        _listenerMock.SimulateClientConnection();

        _receiverMock.SimulateEchoTimeout();

        Assert.AreEqual("Client did not reply", _loggerMock.RecentErrorMessage);
    }
}

关于c# - 单元测试心跳功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53334035/

相关文章:

c# - 从 BackgroundWorker C# 更改控件的属性

unit-testing - 如何在 $route 上对 VueJS 观察者进行单元测试

c# - Dotcover 代码覆盖率 : Getting empty results from command line

c# - 如果 x86 构建,则 Nunit.exe 无法在 Vista 64 位上运行

c# - Xamarin 中的 WebException,使用 HttpClient

c# - 在 Magick.Net 中调整图像大小

c# - XML - 帮助 RSS UTF-8 支持

ios - 测试 userDefaults 和私有(private)函数

c# - 使用 JWT 声明对 .NET Core Web API Controller 进行单元测试

Selenium、FluentAutomation 和 NUnit - 如何为每个测试用例切换浏览器?