2012-04-03 7 views
9

パート:偽造TCP要求私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); 

今、私はこのスニペットのためのユニットテストを書くしたいと思います。私はクライアント接続を偽装し、任意のデータを渡し、サーバーがそれをどのように処理するかを確認したい。

C#でどうすればよいですか?

編集:
私が模擬したいのは、接続自体です。ネットワーク接続を避けたいのですが。

+0

あなたは本当にソケットに接続する必要があると思います...?たぶん私はあなたの質問が不足しているだけで、別のソケットを開き、接続を呼び出し、いくつかのデータを送信する...? – Aerik

+0

これはまさにこの質問に関するものです:私はソケットを開くべきですか、あるいは私はTCPインターフェイス全体を模倣すべきですか?私は、適切なテストは、ネットワークインターフェイスのような限られたリソースを使用すべきではないと思います。または間違っています。 – emesx

答えて

16

ソケットを聴いている場合は単体テストではありません。 クライアントと薄いレイヤーをラップし、代わりにモックを使用してください。この方法で、受信したすべてのデータを偽造することができます。

など。ソケット(簡略化した例を)モック:

はあなたが必要とするすべてのメソッドとのインタフェースISocketを作成します。

public interface ISocket 
{ 
    ISocket Accept(int port); 
    byte[] Receive(int numberOfBytes); 
    bool Send(byte[] data); 
    void Disconnect(); 
    bool Connect(string address, int port); 
} 

は今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 
} 

どこ通常どおりSystem.Net.Sockets.Socketを使用し、代わりにISocketを渡します。 Socketを新規に作成する必要があるときは、TcpSocketを使用します。あなたのシステムのぎざぎざに深くソケットを作成する場合は、TcpSocketを直接新しく作るのではなく、ファクトリを作成したいかもしれません。テストの下では、別の実装のISocket(Mock)を渡すことができます(おそらく工場を通じて作成されます)。あなたは、Receiveでテストデータを返すMockSocketと呼ばれるISocketの2番目の実装を作成することで、独自のモックを実装することができます。または、無数のモックフレームワークを使ってそれを行うことができます。

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... 
} 

これかもしれないが多くの労力のように見えますが、すべてが、おもちゃのシステムに境界APIは、テストのためだけでなく、柔軟滞在するだけではなく、薄い層の背後に隠されなければなりません。例えば、System.Net.Socketの代わりにもっと強力なソケットライブラリを使いたい場合、TcpSocketはそれを自分のコードでソケットのあらゆる使用を変更することなく使用できるようにすることができます。これはまた、具体的な実装にプログラミングするのではなく、インターフェイスへのプログラミングが良いアイデアである理由です。実装を簡単に切り替えることができます(ただし、すべてのクラスへのインターフェイスを作成する必要はありません)。このようなことがすべて混乱している場合は、嘲笑についてもっと詳しくお読みください(http://en.wikipedia.org/wiki/Mock_object

+2

これは行く方法です –

+0

よろしいですか。私は、TCPサーバーを持っています - スレッド、TCP接続をリッスンします。そして私はクライアントと通信している - サーバーと通信します。今私はサーバーをテストしています。だから正確に私はクライアントを嘲笑すべきですか?なぜ..私はそれが任意のデータを送信するように強制することができますので。私は、TCPインターフェイスを嘲笑するC#についてもっと考えていましたので、トラフィックは生成されませんでした。さらにメモリ内のスタイル.. – emesx

+0

TcpClientクラスをモックする必要があります。 – EricSchaefer

3

最も簡単な方法は、Streamが必要な操作を実行することです。そうすれば、必要なデータを持っているMemoryStreamを単に渡すことができます。これはクライアントの初期化コードのテストには役立ちませんが、それが重要かどうかは不明です。

また、クライアントごとに新しいThreadを開始しないでください。代わりにTaskなどの方法を使用してください。

+0

チップのおかげで! – emesx

2

これをユニットテストするには、おそらく.NET TCP APIの上に抽象レイヤーを作成する必要があります。単体テストは、通常、コードの入力、出力、インタラクションをテストするためのもので、コードと他のAPIとの相互作用をテストするためのものではありません。それが統合テストの役割です。作成する抽象レイヤーは単体テストではありませんが、コードの残りの部分をテストするために、疑似オブジェクトやモックオブジェクトと簡単に交換することができます。

関連する問題