模拟 Networkstream.Read

6

我一直在尝试模拟网络流以进行一些单元测试。

到目前为止,使用Moq,我最好的方法是使用流的包装器,然后模拟我的接口。

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

    void Flush();

    bool DataAvailable { get; }

    bool CanRead { get; }

    void close();
}

问题是,虽然这给了我一个开始,但我实际上想测试一些字节数组值,如读入我的读取缓冲区。当调用模拟对象上的Read()时,我如何将一些测试数据返回到缓冲区中?

3个回答

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

1
我想要做的是设置模拟networkStream,以便在调用Read()时它会将一个字节数组返回到缓冲区中。这样我就可以根据已知的字节数组结果来测试我的代码。从您的回复中,我只是设置了返回值? - obaylis

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 也许您可以编写一个集成测试,或者使您的代码依赖于抽象的流类。
在您的测试中,您可以使用MemoryStream来检查当从流中获取数据时类的正确行为。

感谢你的回答。这是一篇有趣的文章。 - obaylis

1
在Rhinomocks中,这非常容易实现,因为NetworkStream上的重要方法都是虚拟的,所以您可以使用MockRepository简单地创建一个存根。更好的是,它理解传递给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);

不需要包装器。

我对Moq的经验很少,但如果它不支持类似的功能,我会感到惊讶。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接