运行 在使用 XUnit 的测试中

Running in Test using XUnit

第一次尝试学习测试驱动设计。我有一个这样的服务器:

public class ServerEngine
    {
        private static Socket _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        private static List<Socket> _clientSockets = new List<Socket>();
        private static byte[] _buffer = new byte[1024];

        public ServerEngine()
        {
            SetupServer();
        }

        private void SetupServer()
        {
            Console.WriteLine("Setting up the server...");
            _serverSocket.Bind(new IPEndPoint(IPAddress.Any, 100));

            // Settingup the backlog
            _serverSocket.Listen(1);

            //Listen for connections
            _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
        }

        private void AcceptCallback(IAsyncResult ar)
        {
            // Add the accepted socket to the list of sockets
            Socket socket = _serverSocket.EndAccept(ar);
            _clientSockets.Add(socket);
            Console.WriteLine("A client has connected");
            // listen for messages coming from the new accepted socket
            socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
            // Start accepting a new connection again
            _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
        }

        private void ReceiveCallback(IAsyncResult ar)
        {
            Socket socket = (Socket)ar.AsyncState;
            try
            {
                var received = socket.EndReceive(ar);
                var dataBuf = new byte[received];
                Array.Copy(_buffer, dataBuf, received);

                var text = Encoding.ASCII.GetString(dataBuf);
                Console.WriteLine($"Text Received: {text}");

                var response = AddToHashSet(text);
                var data = Encoding.ASCII.GetBytes(response.ToString());
                socket.BeginSend(data, 0, data.Length, SocketFlags.None, new AsyncCallback(SendCallback), socket);
                socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
                _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
            }
            catch (SocketException)
            {
                socket.Close();
                Console.WriteLine("A client has disconnected.");
            }
        }

        private void SendCallback(IAsyncResult ar)
        {
            Socket socket = (Socket)ar.AsyncState;
            socket.EndSend(ar);
        }

        private HashSet<TidContainerModel> _tidContainerModels = new HashSet<TidContainerModel>(new TidContainerModelComparer());
        private bool AddToHashSet(string value)
        {
            var tcv = new TidContainerModel
            {
                Tid = value,
                TimeAdded = DateTime.Now,
                Type = 'R',
                Rssi = -444
            };
            return _tidContainerModels.Add(tcv);
        }
    }

我在 Program Main 中调用它来设置服务器。然后我像这样创建了一个 xUnit 测试:

private Socket _clentSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        private ServerEngine serverEngine = new ServerEngine();

        [Fact]
        public void ConnectToServerTest()
        {
            // Arrange
            bool expected = true;

            // Act
            bool actual = LoopConnect();

            // Assert
            Assert.Equal(expected, actual);
        }

        private bool LoopConnect()
        {
            int attempts = 0;
            var connected = false;
            while (!_clentSocket.Connected)
            {
                try
                {
                    attempts++;
                    var ipAddress = new IPEndPoint(IPAddress.Parse("172.16.35.71"), 100);
                    _clentSocket.Connect(ipAddress);
                }
                catch (SocketException se)
                {
                    Console.Clear();
                    Console.WriteLine($"Failed connecting {se.Message}. Reconnecting attempt {attempts}");
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            }

            connected = true;
            Console.Clear();
            Console.WriteLine("Connected to the server");
            return connected;
        }

在不使用测试的情况下,该程序运行良好。但是当我使用测试时,我失败了,错误为:

Server.Test.ServerEngineTest.ConnectToServerTest
   Source: ServerEngineTest.cs line 15
   Duration: 209 ms

  Message: 
System.IO.IOException : The handle is invalid.


  Stack Trace: 
__Error.WinIOError(Int32 errorCode, String maybeFullPath)
Console.GetBufferInfo(Boolean throwOnNoConsole, Boolean& succeeded)
Console.Clear()
ServerEngineTest.LoopConnect() line 51
ServerEngineTest.ConnectToServerTest() line 21

如果我使用控制台应用程序连接到服务器,它工作得很好。我想学习如何在这个项目中使用 xUnit。

看看你的堆栈跟踪,它告诉你问题所在:

  Stack Trace: 
__Error.WinIOError(Int32 errorCode, String maybeFullPath)
Console.GetBufferInfo(Boolean throwOnNoConsole, Boolean& succeeded)
Console.Clear()
ServerEngineTest.LoopConnect() line 51
ServerEngineTest.ConnectToServerTest() line 21

基本上,您正在尝试清除控制台,但您的测试中没有分配任何控制台。这是你永远不应该做的事情,原因有两个:

  1. 你应该嘲笑你的 I/O 才能测试它。
  2. 绝对不要将这种控制台 I/O 与套接字服务混合使用,无论它做什么。使用依赖注入来提取和包含控制台 I/O(或者更好的是,适当的日志记录接口)与启动和维护 TCP 服务器的实际工作分开。