Reputation: 5048
Trying to learn Test Driven Design for the first time. I have a server that goes like this:
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);
}
}
This I call in the Program Main to setup the server. Then I created an xUnit test like so:
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;
}
Without using the Test this program runs fine. But when I use the test, I fail with an error of:
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
If I use a console application to connect to the server, it works perfect. I want to learn how to use the xUnit with this project.
Upvotes: 0
Views: 133
Reputation: 67352
Look at your stack trace, it's telling you the problem:
Stack Trace:
__Error.WinIOError(Int32 errorCode, String maybeFullPath)
Console.GetBufferInfo(Boolean throwOnNoConsole, Boolean& succeeded)
Console.Clear()
ServerEngineTest.LoopConnect() line 51
ServerEngineTest.ConnectToServerTest() line 21
Basically, you're trying to clear the console, but you have no console allocated in your test. Which is something you should never do for two reasons:
Upvotes: 2