1
0
Files
common/AMWD.Common.Test/TcpClientMoq.cs

176 lines
5.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using Moq;
namespace AMWD.Common.Test
{
/// <summary>
/// Wrapps the <see cref="Mock{TcpClient}"/> including the setup.
/// </summary>
public class TcpClientMoq
{
private readonly Mock<NetworkStream> _streamMock;
/// <summary>
/// Initializes a new instance of the <see cref="TcpClientMoq"/> class.
/// </summary>
public TcpClientMoq()
{
Callbacks = new();
Response = new byte[0];
_streamMock = new();
_streamMock
.Setup(s => s.WriteAsync(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<CancellationToken>()))
.Callback<byte[], int, int, CancellationToken>((buffer, offset, count, _) =>
{
var callback = new TcpClientCallback
{
Buffer = new byte[count],
Offset = offset,
Count = count,
Type = TcpClientCallback.WriteType.Asynchronous
};
Array.Copy(buffer, offset, callback.Buffer, 0, count);
Callbacks.Add(callback);
})
.Returns(Task.CompletedTask);
_streamMock
.Setup(s => s.Write(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>()))
.Callback<byte[], int, int>((buffer, offset, count) =>
{
var callback = new TcpClientCallback
{
Buffer = new byte[count],
Offset = offset,
Count = count,
Type = TcpClientCallback.WriteType.Synchronous
};
Array.Copy(buffer, offset, callback.Buffer, 0, count);
Callbacks.Add(callback);
});
_streamMock
.Setup(s => s.ReadAsync(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<CancellationToken>()))
.Callback<byte[], int, int, CancellationToken>((buffer, offset, count, _) =>
{
byte[] bytes = Response ?? new byte[0];
Array.Copy(bytes, 0, buffer, offset, Math.Min(bytes.Length, count));
})
.ReturnsAsync(Response?.Length ?? 0);
_streamMock
.Setup(s => s.Read(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>()))
.Callback<byte[], int, int>((buffer, offset, count) =>
{
byte[] bytes = Response ?? new byte[0];
Array.Copy(bytes, 0, buffer, offset, Math.Min(bytes.Length, count));
})
.Returns(Response?.Length ?? 0);
Mock = new();
Mock
.Setup(c => c.GetStream())
.Returns(_streamMock.Object);
}
/// <summary>
/// Gets the mocked <see cref="TcpClient"/>.
/// </summary>
public Mock<TcpClient> Mock { get; }
/// <summary>
/// Gets the placed request.
/// </summary>
public List<TcpClientCallback> Callbacks { get; }
/// <summary>
/// Gets the byte response, that should be "sent".
/// </summary>
public byte[] Response { get; set; }
/// <summary>
/// Resets the <see cref="Response"/> and <see cref="Callbacks"/>.
/// </summary>
public void Reset()
{
Response = new byte[0];
Callbacks.Clear();
}
/// <summary>
/// Verifies the number of calls writing asynchronous to the stream.
/// </summary>
/// <param name="times">Number of calls.</param>
public void VerifyWriteAsync(Times times)
=> _streamMock.Verify(s => s.WriteAsync(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<CancellationToken>()), times);
/// <summary>
/// Verifies the number of calls writing synchronous to the stream.
/// </summary>
/// <param name="times">Number of calls.</param>
public void VerifyWriteSync(Times times)
=> _streamMock.Verify(s => s.Write(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>()), times);
/// <summary>
/// Verifies the number of calls reading asynchronous from the stream.
/// </summary>
/// <param name="times">Number of calls.</param>
public void VerifyReadAsync(Times times)
=> _streamMock.Verify(s => s.ReadAsync(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<CancellationToken>()), times);
/// <summary>
/// Verifies the number of calls reading synchronous from the stream.
/// </summary>
/// <param name="times">Number of calls.</param>
public void VerifyReadSync(Times times)
=> _streamMock.Verify(s => s.Read(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>()), times);
/// <summary>
/// Represents the placed TCP request.
/// </summary>
public class TcpClientCallback
{
/// <summary>
/// Gets or sets the type (a/synchronous call).
/// </summary>
public WriteType Type { get; set; }
/// <summary>
/// Gets or sets the buffer content.
/// </summary>
public byte[] Buffer { get; set; }
/// <summary>
/// Gets or sets the offset.
/// </summary>
public int Offset { get; set; }
/// <summary>
/// Gets or sets the byte count.
/// </summary>
public int Count { get; set; }
/// <summary>
/// Lists the possible request types.
/// </summary>
public enum WriteType
{
/// <summary>
/// The request was synchronous.
/// </summary>
Synchronous = 1,
/// <summary>
/// The request was asynchronous.
/// </summary>
Asynchronous = 2
}
}
}
}