Tôi đang làm việc trên một lớp học sử dụng UdpClient và cố gắng tìm hiểu/sử dụng phương pháp TDD sử dụng NUnit và Moq trong quá trình này.Mock UdpClient để kiểm tra đơn vị
Một trần xương một phần của lớp học của tôi cho đến nay như sau:
public UdpCommsChannel(IPAddress address, int port)
{
this._udpClient = new UdpClient();
this._address = address;
this._port = port;
this._endPoint = new IPEndPoint(address, port);
}
public override void Open()
{
if (this._disposed) throw new ObjectDisposedException(GetType().FullName);
try
{
this._udpClient.Connect(this._endPoint);
}
catch (SocketException ex)
{
Debug.WriteLine(ex.Message);
}
}
public override void Send(IPacket packet)
{
if (this._disposed) throw new ObjectDisposedException(GetType().FullName);
byte[] data = packet.GetBytes();
int num = data.Length;
try
{
int sent = this._udpClient.Send(data, num);
Debug.WriteLine("sent : " + sent);
}
catch (SocketException ex)
{
Debug.WriteLine(ex.Message);
}
}
.
.
Đối Send phương pháp, tôi có kiểm tra đơn vị sau đây vào lúc này:
[Test]
public void DataIsSent()
{
const int port = 9600;
var mock = new Mock<IPacket>(MockBehavior.Strict);
mock.Setup(p => p.GetBytes()).Returns(new byte[] { }).Verifiable();
using (UdpCommsChannel udp = new UdpCommsChannel(IPAddress.Loopback, port))
{
udp.Open();
udp.Send(mock.Object);
}
mock.Verify(p => p.GetBytes(), Times.Once());
}
.
.
Tôi không hài lòng với điều đó bởi vì nó đang sử dụng một địa chỉ IP thực, mặc dù chỉ có localhost, và UdpClient bên trong lớp là vật lý gửi dữ liệu đến nó. Vì vậy, đây không phải là một thử nghiệm đơn vị thực sự theo như tôi hiểu nó.
Vấn đề là, tôi không thể xoay quanh chính xác những gì cần làm. Tôi có nên thay đổi lớp học của mình và vượt qua UdpClient mới như một sự phụ thuộc không? Giả lập IPAddress bằng cách nào đó?
Đấu tranh một chút, vì vậy tôi cần dừng lại ở đây để xem tôi có đi đúng hướng hay không trước khi tiếp tục. Bất kỳ lời khuyên nào được đánh giá cao!
(Sử dụng NUnit 2.5.7, Moq 4.0 và C# WinForms.) .
.
UPDATE:
OK, tôi đã refactored mã của tôi như sau:
Tạo một giao diện IUdpClient:
public interface IUdpClient
{
void Connect(IPEndPoint endpoint);
int Send(byte[] data, int num);
void Close();
}
.
Tạo một lớp adapter để quấn hệ thống lớp UdpClient:
public class UdpClientAdapter : IUdpClient
{
private UdpClient _client;
public UdpClientAdapter()
{
this._client = new UdpClient();
}
#region IUdpClient Members
public void Connect(IPEndPoint endpoint)
{
this._client.Connect(endpoint);
}
public int Send(byte[] data, int num)
{
return this._client.Send(data, num);
}
public void Close()
{
this._client.Close();
}
#endregion
}
.
refactored Clas UdpCommsChannel tôi để yêu cầu một thể hiện của một IUdpClient tiêm qua các nhà xây dựng:
public UdpCommsChannel(IUdpClient client, IPEndPoint endpoint)
{
this._udpClient = client;
this._endPoint = endpoint;
}
.
kiểm tra đơn vị của tôi bây giờ trông như thế này:
[Test]
public void DataIsSent()
{
var mockClient = new Mock<IUdpClient>();
mockClient.Setup(c => c.Send(It.IsAny<byte[]>(), It.IsAny<int>())).Returns(It.IsAny<int>());
var mockPacket = new Mock<IPacket>(MockBehavior.Strict);
mockPacket.Setup(p => p.GetBytes()).Returns(new byte[] { }).Verifiable();
using (UdpCommsChannel udp = new UdpCommsChannel(mockClient.Object, It.IsAny<IPEndPoint>()))
{
udp.Open();
udp.Send(mockPacket.Object);
}
mockPacket.Verify(p => p.GetBytes(), Times.Once());
}
.
Bất kỳ nhận xét nào khác đều được chào đón.
Cảm ơn trả lời của bạn. Bạn có ý nói "... bạn có thể giả lập ICommunicator ..."? – Andy
xin hãy xem chỉnh sửa –
Yep, điều này có ý nghĩa hơn bây giờ, cảm ơn. – Andy