2012-11-10 25 views
6

我一直在試圖模擬網絡流的一些單元測試。模擬Networkstream.Read

到目前爲止,使用Moq最好的我想出的是使用包裝的流,然後模擬我的界面。

public interface INetworkstreamWrapper 
{ 
    int Read(byte[] buffer, int offset,int size); 

    void Flush(); 

    bool DataAvailable { get; } 

    bool CanRead { get; } 

    void close(); 
} 

問題,而這給了我一個開始,其實我是想測試一些字節數組值讀入到我的讀取緩衝區。在模擬對象上調用Read()時,如何返回一些測試數據到緩衝區?

回答

4

您可以使用一個回調來訪問傳遞的參數,並改變它們:

public void TestRead() 
{ 
    var streamMock = new Mock<INetworkstreamWrapper>(); 

    streamMock 
      .Setup(m => m.Read(It.IsAny<byte[]>(), 
           It.IsAny<int>(), 
           It.IsAny<int>())) 
      .Callback((byte[] buffer, int offset, int size) => buffer[0] = 128); 

    var myBuffer = new byte[10]; 
    streamMock.Object.Read(myBuffer,0,10); 

    Assert.AreEqual(128, myBuffer[0]); 
} 

但我建議你重新考慮你的策略關於那種嘲弄,請參閱: http://davesquared.net/2011/04/dont-mock-types-you-dont-own.html

也許你可以寫一個集成測試,或者, e您的代碼依賴於抽象的Stream類。

在測試中,您可以使用MemoryStream在從Stream中獲取數據時檢查類的正確行爲。

+0

感謝您的回答。有趣的文章。 – obaylis

4

您可以使用Setup做到這一點:

[Test] 
public void MockStreamTest() 
{ 
    var mock = new Mock<INetworkstreamWrapper>(); 
    int returnValue = 1; 
    mock.Setup(x => x.Read(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>())) 
        .Returns((byte[] r,int o, int s) => 
            { 
             r[0] = 1; 
             return returnValue; 
            }); 
    var bytes = new byte[1024]; 
    var read = mock.Object.Read(bytes , 1, 1); 
    //Verify the the method was called with expected arguments like this: 
    mock.Verify(x => x.Read(bytes, 1, 1), Times.Once()); 
    Assert.AreEqual(returnValue, read); 
    Assert.AreEqual(1,bytes[0]); 
} 
+0

我想要做的就是設置模擬networkStream,以便在我調用Read()時它將返回一個字節數組到緩衝區。這樣我就可以根據已知的字節數組結果來測試我的代碼。從你的回答中,我只是設置了返回值? – obaylis

+0

更新了我的回答 –

0

在Rhinomocks中,這很容易,因爲NetworkStream上的重要方法是虛擬的,因此您可以使用MockRepository簡單地創建存根。更妙的是,它知道傳遞給閱讀方法的字節數組是一個輸出數組,這樣你就可以使用此代碼完全踩滅調用閱讀():

NetworkStream stream = MockRepository.GenerateStub<NetworkStream>(); 
stream.Stub(x => x.Read(Arg<byte[]>.Out(bytes).Dummy, Arg<int>.Is.Anything, Arg<int>.Is.Anything)) 
     .Return(bytes.Length); 

無需包裝。

我對Moq的經驗很少,但如果它不支持類似的東西,我會感到驚訝。