終於在下班前,把設置NetworkStream.Read 的 buffer 參數的難點搞定了。
第一次在網上 show 一下自己的代碼:
[TestFixture]
/**//// <summary>
/// FirstFixture 的摘要說明。
/// </summary>
public class FirstFixture ...{
MockRepository mocks = new MockRepository();
System.IDisposable order;
ITcpClient clIEntMock;
INetworkStream streamMock;
MainClass a;
private string[] expectedString;
private int expectedStringIndex;
public FirstFixture() ...{}
[SetUp]
public void SetUp() ...{
order = mocks.Ordered();
clientMock = (ITcpClient)mocks.CreateMock(typeof(ITcpClIEnt));
streamMock = (INetworkStream)mocks.CreateMock(typeof(INetworkStream));
a = new MainClass(clIEntMock);
clIEntMock.Connect(serverIp, serverPort);
Expect.Call(clIEntMock.GetStream()).Return(streamMock);
Expect.On(clientMock).Call(clIEntMock.GetLocalPort()).Return(localPort);
}
[TearDown]
public void TearDown() ...{
mocks.VerifyAll();
}
delegate bool NetworkStreamWriteDelegate(byte[] actualBuffer, int actualOffset, int actualSize);
delegate int NetworkStreamReadDelegate(byte[] buffer, int offset, int size);
bool NormalWriteMessageAssert(byte[] actualBuffer, int actualOffset, int actualSize) ...{
expectedString[0] = "prefix";
string actualBufferString = Encoding.ASCII.GetString(actualBuffer);
Assert.AreEqual(expectedString[0], actualBufferString.Substring(0, expectedString[0].Length));
//assert clIEnt.write()來的timestamp
System.DateTime actualTimeStamp = System.DateTime.ParseExact(actualBufferString.Substring(expectedString[0].Length, 20), "dd-MMM-yyyy HH:mm:ss", System.Globalization.DateTimeFormatInfo.InvariantInfo);
// 時間差小於2秒
Assert.Greater(2, System.Math.Abs(System.DateTime.Now.Subtract(actualTimeStamp).TotalSeconds));
expectedString[0] = "postfix";
Assert.AreEqual(expectedString[0], actualBufferString.Substring(actualBufferString.Length - expectedString[0].Length, expectedString[0].Length));
return true;
}
int SetReadBuffer(byte[] buffer, int offset, int size) ...{
byte[] expectedBuffer = Encoding.ASCII.GetBytes(expectedString[expectedStringIndex++]);
for (int pos = 0; pos < expectedBuffer.Length; pos++) ...{
buffer[pos] = expectedBuffer[pos];
}
return expectedBuffer.Length;
}
[Test]
public void Normal() ...{
expectedString = new string[3];
expectedString[0] = "static write string";
streamMock.Write(Encoding.ASCII.GetBytes(expectedString[0]), 0, expectedString[0].Length);
// write的buffer中,包含了當前的時間戳信息。利用Callback實現復雜的assert
streamMock.Write(null, 0, 0);
LastCall.Callback(new NetworkStreamWriteDelegate(NormalWriteMessageAssert));
// 利用Expect.Do()和delegate,實現對多次Stream.Read()的mock
// 這是在Rhino.Mocks google group中Stream.Read的貼子的基礎上完善的。
// 感謝Terriy
byte[] responseBuffer = new byte[1024];
expectedStringIndex = 1;
expectedString[1] = "first server response";
Expect.Call(streamMock.Read(responseBuffer, 1, 1024)).Constraints(Is.TypeOf(typeof(byte [])), Is.Equal(0), Is.Equal(responseBuffer.Length))
.Do(new NetworkStreamReadDelegate(SetReadBuffer));
expectedString[2] = "server second string";
Expect.Call(streamMock.Read(responseBuffer, 2, 1024)).Constraints(Is.TypeOf(typeof(byte [])), Is.Equal(0), Is.Equal(responseBuffer.Length))
.Do(new NetworkStreamReadDelegate(SetReadBuffer));
clIEntMock.Close();
order.Dispose();
mocks.ReplayAll();
a.Interact();
}