gpt4 book ai didi

c# - 如何在单元测试中最小化 NetworkStream?

转载 作者:可可西里 更新时间:2023-11-01 03:08:07 25 4
gpt4 key购买 nike

我使用 Moq 和 NUnit 作为单元测试框架。

我写了一个方法,将 NetworkStream 对象作为参数:

public static void ReadDataIntoBuffer(NetworkStream networkStream, Queue dataBuffer)
{
if ((networkStream != null) && (dataBuffer != null))
{
while (networkStream.DataAvailable)
{
byte[] tempBuffer = new byte[512];

// read the data from the network stream into the temporary buffer
Int32 numberOfBytesRead = networkStream.Read(tempBuffer, 0, 512);

// move all data into the main buffer
for (Int32 i = 0; i < numberOfBytesRead; i++)
{
dataBuffer.Enqueue(tempBuffer[i]);
}
}
}
else
{
if (networkStream != null)
{
throw new ArgumentNullException("networkStream");
}

if (dataBuffer != null)
{
throw new ArgumentNullException("dataBuffer");
}
}
}

现在我正在考虑为这个方法重写我的单元测试,因为以前编写的测试依赖于真实的 NetworkStream 对象并且不太好处理。

如何模拟 NetworkStream?我正在使用前面提到的最小起订量。有可能吗?如果不是,我该如何解决这个问题?

期待您的反馈!

这是以前的解决方案:

public static void ReadDataIntoBuffer(Stream dataStream, Queue dataBuffer)
{
if ((networkStream != null) && (dataBuffer != null))
{
byte[] tempBuffer = new byte[512];
Int32 numberOfBytesRead = 0;

// read the data from the network stream into the temporary buffer
while ((numberOfBytesRead = dataStream.Read(tempBuffer, 0, 512) > 0)
{
// move all data into the main buffer
for (Int32 i = 0; i < numberOfBytesRead; i++)
{
dataBuffer.Enqueue(tempBuffer[i]);
}
}
}
else ...
}

更新:

我又重写了我的类(class)。使用以前的解决方案进行单元测试很顺利,但实际应用示例向我展示了为什么我不可能使用将 Stream 对象传递到我的方法中的(否则很棒)建议。

首先,我的应用程序依赖于持续的 TCP 连接。如果您使用 Stream.Read(这是可能的)并且没有要接收的数据,它将阻止执行。如果指定超时,则在未收到数据时将抛出异常。这种行为对于我需要的(相当简单的)应用程序来说是 Not Acceptable 。我只需要一个简单的、持续的 TCP 连接。因此,拥有 NetworkStream.DataAvailable 属性对我的实现至关重要。

当前的解决方案:

我最终为 NetworkStream 编写了一个接口(interface)和一个包装器。我还最终将临时接收缓冲区的字节数组传递给了方法。单元测试它现在工作得相当好。

public static void ReadDataIntoBuffer(INetworkStream networkStream, Queue dataBuffer, byte[] tempRXBuffer)
{
if ((networkStream != null) && (dataBuffer != null) && (tempRXBuffer != null))
{
// read the data from the network stream into the temporary buffer
while(networkStream.DataAvailable)
{
Int32 numberOfBytesRead = networkStream.Read(tempRXBuffer, 0, tempRXBuffer.Length);

// move all data into the main buffer
for (Int32 i = 0; i < numberOfBytesRead; i++)
{
dataBuffer.Enqueue(tempRXBuffer[i]);
}
}
}
else ...
}

这是我使用的单元测试:

public void TestReadDataIntoBuffer()
{
var networkStreamMock = new Mock<INetworkStream>();
StringBuilder sb = new StringBuilder();

sb.Append(_testMessageConstant1);
sb.Append(_testMessageConstant2);
sb.Append(_testMessageConstant3);
sb.Append(_testMessageConstant4);
sb.Append(_testMessageConstant5);


// ARRANGE
byte[] tempRXBuffer = Encoding.UTF8.GetBytes(sb.ToString());

// return true so that the call to Read() is made
networkStreamMock.Setup(x => x.DataAvailable).Returns(true);

networkStreamMock.Setup(x => x.Read(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>())).Callback(() =>
{
// after the call to Read() re-setup the property so that we
// we exit the data reading loop again
networkStreamMock.Setup(x => x.DataAvailable).Returns(false);

}).Returns(tempRXBuffer.Length);

Queue resultQueue = new Queue();

// ACT
ReadDataIntoBuffer(networkStreamMock.Object, resultQueue, tempRXBuffer);

// ASSERT
Assert.AreEqual(Encoding.UTF8.GetBytes(sb.ToString()), resultQueue.ToArray());
}

最佳答案

您不能使用 moq 模拟 NetworkStream,因为它不是抽象类或接口(interface)。但是,您可以在其之上创建一个抽象并更改您的方法以接受该抽象的实例。它可能是这样的:

public interface IMyNetworkStream
{
int Read([In, Out] byte[] buffer, int offset, int size);
bool DataAvailable {get;}
}

现在您创建一个实现该接口(interface)的类:

public class MyNetworkStream : IMyNetworkStream
{
private NetworkStream stream;

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

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

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

}

现在您可以更改方法签名以使用 IMyNetworkStream 的实例并使用 Moq 创建 IMyNetworkStream 的模拟。

关于c# - 如何在单元测试中最小化 NetworkStream?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2176975/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com