微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 模拟复杂的第三方库

我有一个使用第三方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,ref bool cancel);

public interface IFTPClient<T1,T2> : Idisposable
{
    string Connect(string hostname,System.Net.NetworkCredential credential);
    ulong PutFile(
        string localFileName,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,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,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);
}

在像这样的情况下,通常的做法是什么?我的方法似乎很混乱,我想知道是否有更简单的方法.谢谢.

解决方法

我认为这只会感觉很乱,因为你已经让第三方代表应对了,但对我来说它看起来像一个非常标准的抽象/模拟方法.

我唯一的评论是FTPServerConnection的结构看起来有点不标准;它的编写方式你必须在无效状态下实例化一个(即一个没有客户端细节的状态)然后调用Init(),它本身调用Connect()(从测试的外观来看,它从不被服务器的客户端调用)类).我会说在FTPServerConnection构造函数中提供Init()的参数更为正常,然后完全删除Init()方法并让客户端执行此操作:

var ftpClient = new Mock<IFTPClient<object,object>>();

using (var ftpServer = new FTPServerConnection<object,object>(
     ftpClient.Object,"passwd"))
{
    ftpServer.Connect();
}

…但是,关于你抽象FTP库的方式,我认为这是一个很好的方式:)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐