我有一个使用 3rd 方 FTP 库http://ftps.codeplex.com/的类,我想模拟它,以便我可以对那个类而不是 FTP 库进行单元测试。我已经做到了,但对我来说感觉很乱。具体来说,该类使用了 AlexPilotti.FTPS.Client.FTPSClient 类的这些方法:
public string Connect(string hostname, ESSLSupportMode sslSupportMode)
public ulong PutFile(
string localFileName, string remoteFileName,
FileTransferCallback transferCallback)
委托 AlexPilotti.FTPS.Client.FileTransferCallback 如下所示:
public delegate void FileTransferCallback(
FTPSClient sender, ETransferActions action,
string localObjectName, string remoteObjectName,
ulong fileTransmittedBytes, ulong? fileTransferSize, ref bool cancel);
您会看到一个问题,因为 PutFile 从 FTP 库中获取了委托,并且该委托也从库中获取了两种不同的类型。我决定使用泛型与这些类型分离。
为了能够创建模拟对象,我创建了一个接口,然后创建了一个派生类,它是 FTP 库功能的包装器。
// Interface so that dependency injection can be used.
public delegate void FileTransferCallback<T1, T2>(T1 sender, T2 action,
string localObjectName, string remoteObjectName,
ulong fileTransmittedBytes, ulong? fileTransferSize,
ref bool cancel);
public interface IFTPClient<T1, T2> : IDisposable
{
string Connect(string hostname, System.Net.NetworkCredential credential);
ulong PutFile(
string localFileName, string remoteFileName,
FileTransferCallback<T1, T2> transferCallback);
}
// Derived class, the wrapper
using FTPSClient = FTPS.Client.FTPSClient;
using ETransferActions = FTPS.Client.ETransferActions;
public class FTPClient : IFTPClient<FTPSClient, ETransferActions>
{
public FTPClient()
{
client = new AlexPilotti.FTPS.Client.FTPSClient();
}
public ulong PutFile(
string localFileName, string remoteFileName,
FileTransferCallback<FTPSClient, ETransferActions> transferCallback)
{
callback = transferCallback;
return client.PutFile(localFileName, remoteFileName, TransferCallback);
}
public void Dispose()
{
client.Dispose();
}
public string Connect(
string hostname, System.Net.NetworkCredential credential)
{
return client.Connect(hostname, credential,
FTPS.Client.ESSLSupportMode.ClearText);
}
void TransferCallback(
FTPS.Client.FTPSClient sender, FTPS.Client.ETransferActions action,
string localObjectName, string remoteObjectName,
ulong fileTransmittedBytes, ulong? fileTransferSize,
ref bool cancel)
{
callback.Invoke(sender, action, localObjectName, remoteObjectName,
fileTransmittedBytes, fileTransferSize, ref cancel);
}
private AlexPilotti.FTPS.Client.FTPSClient client;
private FileTransferCallback<FTPSClient, ETransferActions> callback;
}
这里有一个使用这个接口的类,我对它进行了单元测试。我将它剥离了一点,所以只使用了 Connect 方法,但我希望它仍然能说明我的问题。
public class FTPServerConnection<T1, T2>
{
public void Init(
IFTPClient<T1, T2> client, string serverName,
string userName, string passwd)
{
IsConnected = false;
ServerName = serverName;
UserName = userName;
Passwd = passwd;
ftpClient = client;
Connect();
}
public void Connect()
{
ftpClient.Connect(
ServerName,
new System.Net.NetworkCredential(UserName, Passwd));
}
public string ServerName { protected set; get; }
public string UserName { protected set; get; }
public string Passwd { protected set; get; }
public bool IsConnected { protected set; get; }
private IFTPClient<T1, T2> ftpClient;
}
最后是单元测试:
[TestMethod()]
public void FTPServerConnectionConstructorTest()
{
var ftpClient = new Mock<IFTPClient<object, object>>();
var ftpServer = new FTPServerConnection<object, object>();
ftpServer.Init(ftpClient.Object, "1.2.3.4", "user", "passwd");
Assert.AreEqual("1.2.3.4", ftpServer.ServerName);
Assert.AreEqual("user", ftpServer.UserName);
Assert.AreEqual("passwd", ftpServer.Passwd);
}
在这种情况下,通常的方法是什么?我的方法似乎很混乱,我想知道是否有更简单的方法。谢谢。