简体   繁体   English

模拟Networkstream.Read

[英]Mock Networkstream.Read

I've been trying to mock a network stream for some unit tests. 我一直试图模拟网络流进行一些单元测试。

So far, using Moq the best I've come up with is to use a wrapper for the stream and then mock my interface. 到目前为止,使用Moq我得到的最好的是使用流的包装器然后模拟我的界面。

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

    void Flush();

    bool DataAvailable { get; }

    bool CanRead { get; }

    void close();
}

Question is, whilst that gives me a start, I actually want to test some byte array values as read into my read buffer. 问题是,虽然这给了我一个开始,但实际上我想测试一些字节数组值作为读入我的读缓冲区。 How can I return some test data into the buffer when calling Read() on the mock object? 在模拟对象上调用Read()时,如何将一些测试数据返回到缓冲区?

You can use Setup to do this: 您可以使用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]);
}

You can use a callback to gain access to the passed parameter and alter them: 您可以使用回调来访问传递的参数并更改它们:

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]);
}

But I would suggest you rethink your strategy about that kind of mocking, see: http://davesquared.net/2011/04/dont-mock-types-you-dont-own.html 但我建议你重新考虑一下这种嘲弄的策略,请参阅: http//davesquared.net/2011/04/dont-mock-types-you-dont-own.html

Maybe you could write an integration test instead, or make your code depend on the abstract Stream class. 也许您可以编写集成测试,或者让您的代码依赖于抽象Stream类。

In your test you could then use a MemoryStream to check your class correct behaviour when fetching data from the Stream. 在测试中,您可以使用MemoryStream在从Stream中获取数据时检查类的正确行为。

In Rhinomocks, this is very easy, as the important methods on NetworkStream are virtual, and so you can simply create a stub using the MockRepository. 在Rhinomocks中,这非常简单,因为NetworkStream上的重要方法是虚拟的,因此您可以使用MockRepository简单地创建存根。 Even better, it understands that the byte array passed to the Read method is an output array, so you can completely stub out a call to Read() using this code: 更好的是,它理解传递给Read方法的字节数组是一个输出数组,因此您可以使用以下代码完全删除对Read()的调用:

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);

No wrapper required. 不需要包装。

I've had very little experience with Moq but I'd be surprised if it didn't support something similar. 我对Moq的经验很少,但如果它不支持类似的东西,我会感到惊讶。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM