ユニットテストフレームワークとして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をモックするにはどうすればよいですか?前述のように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 ...
}
アップデート:
クラスをもう一度書き直しました。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 ...
}
そして、これが私が使用する単体テストです:
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());
}