如何对异步监听的服务器进行单元测试

时间:2015-07-23 18:17:40

标签: c# unit-testing mocking moq

我已经传递了一些代码,需要添加一些单元测试。

有问题的类是一个Socket服务器,它会异步侦听任何尝试连接的客户端,并将它们添加到套接字列表中以侦听数据。显然还有更多的东西,但这应该足以开始。

课程大纲如下:

public class MyServer
{
    private Socket _Server;
    private List<MyClient> _clients;

    public int ClientCount
    {
        _clients.Count;
    }

    public void StartListening()
    {
        _Server = new Socket(...)
        ... // Configure the socket
        _Server.BeginAccept(new AsyncCallback(AddPotentialClient), null);
    }

    private void AddPotentialClient(IAsyncResult result)
    {
        var clientSocket = (Socket)result.AsyncState;
        var newClient = new MyClient(clientSocket);

        _clients.Add(newClient);
    }
}

作为起点,我首先要检查当客户端成功注册时,已注册客户端数(ClientCount)增加1。由于代码不能使单元测试变得非常简单所以我开始介绍一个ISocket接口和SocketAdapter包装来帮助进行模拟。然后我修改了StartListening()方法,以便可以注入模拟,如下所示:

public void StartListening(ISocket server)
{
    _Server = server;
    _Server.BeginAccept(new AsyncCallback(AddPotentialClient), null);
}

这是我陷入困境的地方。我可以启动一个模拟器,我可以将模拟器放入类中,我知道我想要检查什么但是我应该如何配置模拟以刺激我正在检查的增量。如果可能的话,我不想假设MyServer类的内部状态,如果它有助于使测试更容易,我很乐意重构现有的代码。

到目前为止,我已经使用moq进行了以下测试:

[Test]
public void ClientConnecting_Increments_ClientCountBy1()
{
    var testServer = new MyServer();
    var mockASyncResult = new Mock<IAsyncResult>();
    var mockSocket = new Mock<ISocket>();

    // mockASyncResult needs to be configured so that it can be cast to an <ISocket>

    // Forwards configured mockASyncResult to AddPotentialClient() method
    mockSocket.Setup(x => x.BeginAccept(It.IsAny<AsyncCallack>(), null))
              .Returns(mockASyncResult.Object);

    _manager.StartListening(mockSocket.Object);

    Assert.That(_manager.ClientCount, Is.EqualTo(ONE_CLIENT));
}

1 个答案:

答案 0 :(得分:0)

对于单元测试,我使用FakeItEasy库。 你可以伪造你的ISocket实例:

ISocket server = A.Fake<ISocket>();
A.CallTo(() => server.BeginAccept(A<AsyncCallback>.Ignored, null)
 .ReturnsLazily((AsyncCallback callback) => callback(null));

myServer.StartListening(server);