Tim*_*sig 16 c# unit-testing moq mocking networkstream
我正在使用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");
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在我正在考虑为这个方法重新编写单元测试,因为之前编写的测试依赖于真正的NetworkStream对象,并且不是很好处理.
我该如何模拟NetworkStream?我之前正在使用Moq.有可能吗?如果不是,我怎么能解决这个问题?
期待您的反馈!
这是 以前的解决方案:
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 ...
}
Run Code Online (Sandbox Code Playgroud)
更新:
我再次重写了我的课程.使用之前的解决方案进行单元测试很顺利,但现实世界的应用程序示例向我展示了为什么我不可能使用(否则很棒)将Stream
对象传递给我的方法的建议.
首先,我的应用程序依赖于常量的TCP连接.如果您使用Stream.Read
(可能)并且没有数据要接收它将阻止执行.如果指定超时,则在未收到任何数据时将引发异常.对于我需要的(相当简单的)应用程序,这种行为是不可接受的.我只需要一个简单的,连续的TCP连接.因此,拥有该NetworkStream.DataAvailable
属性对我的实施至关重要.
在目前的解决方案:
我最终为NetworkStream编写了一个接口和一个包装器.我还最终将临时接收缓冲区的字节数组传递给方法.单元测试现在运行得相当好.
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 ...
}
Run Code Online (Sandbox Code Playgroud)
这是我使用的单元测试:
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());
}
Run Code Online (Sandbox Code Playgroud)
Kla*_*sen 17
你不能NetworkStream
用moq 来模拟它,因为它不是抽象类或接口.但是,您可以在其上创建抽象并更改您的方法以接受该抽象的实例.它可能是这样的:
public interface IMyNetworkStream
{
int Read([In, Out] byte[] buffer, int offset, int size);
bool DataAvailable {get;}
}
Run Code Online (Sandbox Code Playgroud)
现在,您创建一个实现该接口的类:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以更改方法签名以IMyNetworkStream
使用Moq 的实例并使用Moq来创建模拟IMyNetworkStream
.
归档时间: |
|
查看次数: |
6175 次 |
最近记录: |