Sam Leach
Sam Leach

Reputation: 12966

Mocking a Stream to Read byte[]

My SUT requires a Stream as a parameter, does some work and then returns a byte[]:

public byte[] ProcessRequest(INetworkStream networkStream)

INetworkStream wraps Stream.

I want to mock the Stream parameter to have control over what bytes it reads so I can test the method with these bytes.

stream.Read(buffer, offset, size);

Stream.Read(...) returns an int and populates the buffer parameter.

Using Moq how do I fake the result of the call to INetworkStream.Read(...) (So I control both the length of the byte[] as the return value and also the buffer parameter)?

The Stream wrapper:

public class FakeNetworkStream : INetworkStream
{
    private NetworkStream stream;

    public FakeNetworkStream(NetworkStream ns)
    {
        if (ns == null) throw new ArgumentNullException("ns");
        this.stream = ns;
    }

    public bool DataAvailable
    {
        get
        {
            return this.stream.DataAvailable;
        }
    }

    public int Read(byte[] buffer, int offset, int size)
    {
        return this.stream.Read(buffer, offset, size);
    }

    public void Write(byte[] buffer, int offset, int size)
    {
        this.stream.Write(buffer, offset, size);
    }
}

Upvotes: 3

Views: 10668

Answers (2)

Fernando Magno
Fernando Magno

Reputation: 441

I needed to change the Array Copy method

stream.Setup(x => x.Read(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>()))
              .Callback((byte[] buffer, int offset, int size) =>
              {
                  Array.Copy(tempBuffer, offset, buffer, 0, tempBuffer.Length);
              })
              .Returns((byte[] buffer, int offset, int size) => size);

Upvotes: 0

Daniel Hilgarth
Daniel Hilgarth

Reputation: 174467

It looks like you got a little bit confused by the answer that you linked to. You now have an interface INetworkStream. Simply mock it.
No need to use NetworkStream or Stream in your tests (refer to the last bit of code in the original question, it contains the code you want to use. Disregard the answer that has been posted on the question.)

You would setup your mock something like that:

var stream = new Mock<INetworkStream>();
stream.Setup(x => x.Read(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>()))
      .Callback((byte[] buffer, int offset, int size) =>
                {
                    Array.Copy(tempBuffer, offset, buffer, 0, size) 
                }
               )
      .Returns((byte[] buffer, int offset, int size) => size);

Please note that I am not a Moq user, so my syntax here might be a bit off, but it should convey the idea on how to implement it correctly.

Upvotes: 9

Related Questions