Jump to content

Why provide interface with your library?

Posted on:August 18, 2016 at 02:00 AM

In daily programming activities some of use have the pleasure to use TDD approach :) Going deeper we can introduce the concept of mocks/stubs/shims. For the sake of this article let’s call it mocks. Quite often we use 3rd party libs becuase they offer some functionalities we need. For example:

Simple use-case scenario could be “Take all email from mailbox with subject “ERROR REPORT”. So we have:

public class ErrorEmailHandler
{
    public List<Email>GetErrorEmails()
    {
    .......
    }
}

Let’s say we have a test case: 5 out of 10 emails in mailbox have “ERROR REPORT” subject and those should be returned by GetErrorEmails() method. We don’t care what is the underlying source.

Solution 1

One, pretty naive, test case solution could be to:

  1. Send 10 e-mails where 5 have “ERROR REPORT” subject
  2. Test that we receive 5 back in GetErrorEmails()

Works? Works :)

I hope that you feel the pain of this solution. We are not interested in testing host connection, mail server or even mail client library that we use. We just want to test that our method return only emails with particular subject.

Of course we could have a local process that will act as a mail server… or ftp server… or currency rates server if we need…

Solution 2

Much wiser would be make a wrapper on the 3rd party lib we use. Our wrapper could look like following

interface IEmailClient
{
List<MailMessage> GetMessages();
}

class EmailClient : IEmailClient
{
    public List<MailMessage> GetMessages()
    {
    return ..........
    }
}

Having that in place we can just mock IEmailClient and return those 10 messages were 5 are with “ERROR REPORT” subject in our tests. You should also add some extra tests for the wrapper class (it’s internal state).

Solution 3

Yet there is even better solution. Imagine if IEmailClient interface would be provided by the 3rd party dll. You can skip writing the wrapper class as well. All that can be mocked. This includes FTP Clients, Currency Rate Providers and tons of other services.

I would recommend (also to myself) providing public interfaces for out libraries as often as possible.

Cleaner code-base leads to better quality