2009-08-11 12 views
7

C#でSystem.net.Sockets.Socketクラスをモックしようとしています - NUnitモックを使ってみましたが、具体的なクラスをモックできません。私もRhino Mocksを使ってみましたが、Send(byte [])が呼び出されたときにSocketExceptionがスローされたので、クラスの実際のバージョンを使用したようです。誰も正常に作成し、任意の模擬フレームワークを使用してソケットモックを使用していますか?誰もが.NETでSocketクラスをうまく模擬しましたか?

+13

"あなたはソケットことを呼んで?" いカウント? =] – mdec

答えて

12

Moqでこれらの問題が発生するたびに、私はモックできないものを抽象化するためのインタフェースを作成してしまいます。

したがって、Sendメソッドを実装するISocketインターフェイスがある可能性があります。それからあなたの嘲笑フレームワークを模倣してください。あなたの実際のコードで

は、あなたはそれがあなたのニーズを満たしているかどうかわからないこの

public class MySocket : ISocket 
{ 
    System.Net.Sockets.Socket _socket; 

    public void MySocket(System.Net.Sockets.Socket theSocket) 
    { 
    _socket = theSocket; 
    } 

    public virtual void Send(byte[] stuffToSend) 
    { 
    _socket.Send(stuffToSend); 
    } 

} 

のようなクラスを持っていると思いますが、それはオプションです。

+0

送信方法を仮想にすることも考慮する必要があります。 –

+0

呼び出しが良いです。メソッドをバーチャルにするために編集されました。 – JamieGaines

+4

しかし、そこで止まらないでください。外部APIをエコーするのではなく、コードが通信レイヤから望むものを記述するインタフェースを記述します。これは、バイトではなく構造化された入力を受け入れることを意味します。あるいは、それは文脈に依存します。 –

0

インターフェイスに作成し、テストで模擬し、コード内にラッパークラスを実装し、thinkzigが言ったようにすべてのメソッド呼び出しを.NETソケットに転送する方がよいでしょう。このリンクを見ても同じ問題です:How do you mock out the file system in C# for unit testing?

2

Sendメソッドを呼び出すと、SocketExceptionが発生するのは、Sendメソッドがオーバーライド可能なメソッドではないからです。 RhinoMockがプロパティやメソッドの動作を疑似できるようにするには、インターフェイスで定義するか(モックオフを作成する)、またはオーバーライドする必要があります。

唯一の解決策は、疑似ラッパークラスを作成することです(thinkzigで提案されているように)。

1

thinkzigが提案するメソッド(Socketのアダプタクラス)を使用してコンソールアプリケーションのサンプルを作成しました。それはRhinoMocksとNUnitを使用します。ここでダウンロードすることができます:How to mock System.Net.Sockets.Socket

1

上記のクラスはあなたの送信方法のみをモックします。これは実際にソケットを模倣します。これはSocketをすべて継承し、ISocketインターフェイスを実装します。 ISocketは、インターフェイスには二つの方法で、このようになります

//internal because only used for test code 
internal class SocketWrapper : Socket, ISocket 
{ 
    /// <summary> 
    /// Web Socket 
    /// </summary> 
    public SocketWrapper():base(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) 
    { 
    } 

    //use all features of base Socket 
} 

を模擬する必要がある任意のソケットのメソッドやプロパティの署名を実装する必要が減少しました:

public interface ISocket 
{ 
    void Connect(IPAddress address, int port); 
    int Send(byte[] buffer, int offset, int size, SocketFlags socketFlags, out SocketError errorCode); 
} 

彼らは2つのコンストラクタを持って使用するクラス。 OneはテストのためにISocketをインジェクトし、次にアプリケーションが使用する独自のソケットを作るためにISocketをインジェクトします。

public class HTTPRequestFactory3 
{ 
internal ISocket _socket; 


    /// <summary> 
    /// Creates a socket and sends/receives information. Used for mocking to inject ISocket 
    /// </summary> 
    internal HTTPRequestFactory3(ISocket TheSocket) 
    { 
    _socket = TheSocket as ISocket; 
    this.Setup(); 
    } 

    /// <summary> 
    /// Self Injects a new Socket. 
    /// </summary> 
    public HTTPRequestFactory3() 
    { 
     SocketWrapper theSocket = new SocketWrapper(); 
     _socket = theSocket as ISocket; 
     this.Setup(); 
    } 
} 

次に、あなたのテストは、期待を設定し、ISocketを作成し、上記のクラスは、実際のソケットが使用するすべて同じコードを実行し、それらを確認することができます。このテストでは、セクションコードが検証されます。

[Test] 
    public void NewSocketFactoryCreatesSocketDefaultConstructor() 
     { 
      webRequestFactory = new HTTPRequestFactory3(); 
      Assert.NotNull(webRequestFactory._socket); 
      Socket testSocket = webRequestFactory._socket as Socket; 
      Assert.IsInstanceOf<Socket>(testSocket); 
     } 
関連する問題