title: Mocking complex 3rd party libraries
body: <p>I have a class that uses 3rd party FTP library <a href="http://ftps.codeplex.com/" rel="nofollow">http://ftps.codeplex.com/</a> and I would like to mock it so that I can unit test just that class and not the FTP library. I have done it but it feels messy to me. In detail, the class uses these methods of AlexPilotti.FTPS.Client.FTPSClient class:</p>
  
  <pre><code>public string Connect(string hostname, ESSLSupportMode sslSupportMode)
  public ulong PutFile(
      string localFileName, string remoteFileName,
      FileTransferCallback transferCallback)
  </code></pre>
  
  <p>Delegate AlexPilotti.FTPS.Client.FileTransferCallback looks like this:</p>
  
  <pre><code>public delegate void FileTransferCallback(
      FTPSClient sender, ETransferActions action, 
      string localObjectName, string remoteObjectName,
      ulong fileTransmittedBytes, ulong? fileTransferSize, ref bool cancel);
  </code></pre>
  
  <p>You can see a problem because PutFile takes the delegate from FTP library and that delegate takes two different types from the library as well. I decided to use generics to decouple from these types.</p>
  
  <p>To be able to create a mock object, I created an interface and then a derived class which is a wrapper of the FTP library functionality.</p>
  
  <pre><code>// Interface so that dependency injection can be used.
  public delegate void FileTransferCallback&lt;T1, T2&gt;(T1 sender, T2 action,
      string localObjectName, string remoteObjectName,
      ulong fileTransmittedBytes, ulong? fileTransferSize,
      ref bool cancel);
  
  public interface IFTPClient&lt;T1, T2&gt; : IDisposable
  {
      string Connect(string hostname, System.Net.NetworkCredential credential);
      ulong PutFile(
          string localFileName, string remoteFileName,
          FileTransferCallback&lt;T1, T2&gt; transferCallback);
  }
  
  // Derived class, the wrapper
  using FTPSClient = FTPS.Client.FTPSClient;
  using ETransferActions = FTPS.Client.ETransferActions;
  
  public class FTPClient : IFTPClient&lt;FTPSClient, ETransferActions&gt;
  {
      public FTPClient()
      {
          client = new AlexPilotti.FTPS.Client.FTPSClient();
      }
  
      public ulong PutFile(
          string localFileName, string remoteFileName,
          FileTransferCallback&lt;FTPSClient, ETransferActions&gt; 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&lt;FTPSClient, ETransferActions&gt; callback;
  }
  </code></pre>
  
  <p>Here goes a class that uses this interface and which I unit test. I stripped it down a bit so only the Connect method is used but I hope it still illustrates my problem.</p>
  
  <pre><code>public class FTPServerConnection&lt;T1, T2&gt;
  {
      public void Init(
          IFTPClient&lt;T1, T2&gt; 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&lt;T1, T2&gt; ftpClient;
  }
  </code></pre>
  
  <p>And finally the unit test:</p>
  
  <pre><code>[TestMethod()]
  public void FTPServerConnectionConstructorTest()
  {
      var ftpClient = new Mock&lt;IFTPClient&lt;object, object&gt;&gt;();
      var ftpServer = new FTPServerConnection&lt;object, object&gt;();
      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);
  }
  </code></pre>
  
  <p>What is the usual approach in situations like this one? My approach seems to be messy and I am wondering if there is easier way of doing it. Thanks.</p>