Tôi đang sử dụng Moq & NUnit làm khung kiểm tra đơn vị.Làm thế nào để moq một NetworkStream trong một bài kiểm tra đơn vị?
Tôi đã viết một phương pháp mà được cho một đối tượng NetworkStream như một tham số:
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");
}
}
}
Bây giờ tôi đang xem xét lại viết bài kiểm tra đơn vị của tôi cho phương pháp này kể từ khi các cuộc thử nghiệm bằng văn bản trước đây dựa vào NetworkStream thực các đối tượng và không phải là rất tốt đẹp để xử lý.
Tôi làm cách nào để giả lập NetworkStream? Tôi đang sử dụng Moq như đã đề cập trước đó. Có thể ở tất cả? Nếu không làm thế nào tôi có thể giải quyết vấn đề này?
Mong nhận được phản hồi của bạn!
Đây là giải pháp trước:
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 ...
}
UPDATE:
Tôi đã viết lại lớp học của tôi một lần nữa. Thử nghiệm đơn vị sử dụng giải pháp trước đã ổn nhưng ví dụ ứng dụng trong thế giới thực đã cho tôi thấy tại sao tôi KHÔNG thể sử dụng đề xuất (nếu không tuyệt vời) khi chuyển đối tượng Stream
vào phương thức của tôi.
Trước hết, ứng dụng của tôi dựa trên kết nối TCP không đổi. Nếu bạn sử dụng Stream.Read
(có thể) và không có dữ liệu để nhận nó sẽ chặn việc thực hiện. Nếu bạn chỉ định thời gian chờ, ngoại lệ sẽ bị ném nếu không nhận được dữ liệu nào. Loại hành vi này không được chấp nhận đối với ứng dụng (khá đơn giản) mà tôi cần. Tôi chỉ cần một kết nối TCP không liên tục. Do đó, có tài sản NetworkStream.DataAvailable
là tối quan trọng đối với việc triển khai của tôi.
Các giải pháp hiện tại:
tôi đã kết thúc viết một giao diện và một wrapper để NetworkStream. Tôi cũng đã kết thúc mảng byte cho bộ đệm nhận tạm thời vào phương thức. Đơn vị kiểm tra nó bây giờ hoạt động khá tốt.
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 ...
}
Và đây là bài kiểm tra đơn vị mà tôi sử dụng:
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());
}
Bạn có thể thay đổi 'NetworkStream' thành một' Stream' không? Điều đó có thể làm mọi thứ dễ dàng hơn. –
Tôi đoán tôi có thể làm điều đó. Bạn có thể giải thích cách đó sẽ làm mọi thứ dễ dàng hơn không? Moq có thể giả lập một đối tượng Stream không? –
có, Moq có thể giả lập một luồng vì nó là một lớp trừu tượng, tuy nhiên 'Dòng' không chứa thuộc tính' DataAvailable', vì vậy tôi đề nghị bạn sử dụng cách tiếp cận mà tôi đã nêu bên dưới để thay thế. –