eme*_*esx 9 .net c# networking unit-testing mocking
我的n00b服务器的一部分:
TcpClient client = tcpListener.AcceptTcpClient();
Thread clientThread = new Thread(new ParameterizedThreadStart(handleClientRegistration));
clientThread.Start(client);
...
//and in the clientThread we wait for data
bytesRead = clientStream.Read(message, 0, 4096);
Run Code Online (Sandbox Code Playgroud)
现在我想为这个片段编写单元测试.我想假冒客户端连接,传递任意数据并检查服务器如何处理它.
我该怎么做C#?
编辑:
我想模拟的是连接本身 - 我想避免网络连接.
Eri*_*fer 17
如果它正在监听套接字,则不是单元测试.包裹客户端和薄层,然后使用模拟.这样您就可以伪造所需的所有接收数据.
例如,模拟套接字(简化示例):
使用您需要的所有方法创建一个接口ISocket:
public interface ISocket
{
ISocket Accept( int port );
byte[] Receive( int numberOfBytes );
bool Send( byte[] data );
void Disconnect();
bool Connect( string address, int port );
}
Run Code Online (Sandbox Code Playgroud)
现在创建一个实现ISocket的具体类TcpSocket:
public class TcpSocket : ISocket
{
private Socket socket;
public TcpSocket()
{
socket = new Socket( AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );
}
// implement all methods of ISocket by delegating to the internal socket
}
Run Code Online (Sandbox Code Playgroud)
无论你通常使用System.Net.Sockets.Socket,都要传递一个ISocket.当你需要新建一个Socket时使用TcpSocket.如果您在系统的内部深处创建套接字,则可能需要创建工厂而不是直接新建TcpSocket.在测试中,您可以传递ISocket(模拟)的不同实现(可能通过工厂创建).您可以通过创建一个名为MockSocket的ISocket的第二个实现来实现您自己的模拟,该实现在Receive中返回测试数据,或者您可以使用无数的模拟框架来为您执行此操作.
public class MockSocket : ISocket
{
private byte[] testData;
public void SetTestData(byte[] data)
{
testData = data;
}
public byte[] Receive(int numberOfBytes)
{
return testData;
}
// you need to implement all members of ISocket ofcourse...
}
Run Code Online (Sandbox Code Playgroud)
这可能看起来很费劲,但除了玩具系统外,边界api应该隐藏在薄层后面,不仅用于测试,还要保持灵活性.例如,如果您想使用更强大的套接字库而不是System.Net.Socket,则可以使用TcpSocket,而无需在您自己的代码中更改每个套接字的使用.这也是为什么编程到接口而不是编程到具体实现通常是一个好主意的原因:您可以轻松切换实现(但这并不意味着您应该创建所有类的接口).如果这一切都让您感到困惑,那么您可以阅读更多关于模拟的内容(例如:http://en.wikipedia.org/wiki/Mock_object)