【问题标题】:Mock Networkstream.Read模拟 Networkstream.Read
【发布时间】:2012-11-10 22:42:51
【问题描述】:

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

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

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

    void Flush();

    bool DataAvailable { get; }

    bool CanRead { get; }

    void close();
}

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

【问题讨论】:

    标签: c# .net stream tdd


    【解决方案1】:

    您可以使用回调来访问传递的参数并更改它们:

    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

    也许您可以编写一个集成测试,或者让您的代码依赖于抽象 Stream 类。

    在您的测试中,您可以使用 MemoryStream 来检查您的类在从流中获取数据时的正确行为。

    【讨论】:

    • 感谢您的回答。有趣的文章。
    【解决方案2】:

    您可以使用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]);
    }
    

    【讨论】:

    • 我想做的是设置模拟网络流,以便在我调用 Read() 时它将一个字节数组返回到缓冲区中。这样我就可以根据已知的字节数组结果测试我的代码。根据您的回复,我只是在设置返回值?
    【解决方案3】:

    在 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 的经验很少,但如果它不支持类似的东西,我会感到惊讶。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-30
      • 2016-12-24
      • 1970-01-01
      • 1970-01-01
      • 2012-03-27
      • 1970-01-01
      • 1970-01-01
      • 2014-01-16
      相关资源
      最近更新 更多