13

I'm doing unit testing and in one of my classes I need to send a mail from one of the methods, so using constructor injection I inject an instance of Zend_Mail class which is in Zend framework.

Now some people argue that if a library is stable enough and won't change often then there is no need to wrap it. So assuming that Zend_Mail is stable and won't change and it fits my needs entirely, then I won't need a wrapper for it.

Now take a look at my class Logger that depends on Zend_Mail:

class Logger{
    private $mailer;    
    function __construct(Zend_Mail $mail){
        $this->mail=$mail;
    }    
   function toBeTestedFunction(){
      //Some code
      $this->mail->setTo('some value');
      $this->mail->setSubject('some value');
      $this->mail->setBody('some value');
      $this->mail->send();
     //Some
   }        
}

However, Unit testing demands that I test one component at a time, so I need to mock the Zend_Mail class. In addition I'm violating the Dependency Inversion principle as my Logger class now depends on concretion not abstraction.

Now how can I test Logger in isolation without wrapping Zend_Mail?!

The code is in PHP, but answers doesn't have to be. This is more of a design issue than a language specific feature

2
  • Do you have to use an interface? Doesn't PHP support duck typing? Nov 5, 2012 at 22:42
  • @kevincline well I used PHP because it's the language that I use most, but I'm actually looking for a general solution to problem not limited to PHP only.
    – Songo
    Nov 5, 2012 at 22:53

1 Answer 1

22

You always want to wrap third party types and methods behind an interface. This can be tedious and painful. Sometimes you can write a code generator or use a tool to do this.

But don't be tempted to use the library methods or types throughout your code. To begin with, you will have trouble writing unit tests. Then a license will change, or you'll want to go to a platform not supported by the third party, and you will find that those types and dependencies have woven in and around all your other classes.

The ability to change third party vendors quickly is a huge advantage.

8
  • 5
    "Anything not written by you" is a bit much. Libraries that are part of the standard or platform are difficult to wrap. You probably wouldn't want to wrap all of the .NET components, for example. If the wrappers are just pass through interfaces, or are generated code, I have found little benefit to writing tests. If there is logic in there (combining calls, etc.) tests can be helpful.
    – Ben
    Nov 5, 2012 at 22:14
  • 4
    Upvoted for the last sentence.
    – Blrfl
    Nov 5, 2012 at 22:20
  • 1
    If you refactor properly, any repetitive use of library facilities will be factored out into a service class. No need to define it up front. Nov 5, 2012 at 22:42
  • 4
    -1: Except in cases where the third party library provides a service for which there is a standardized API, this is a huge waste of time andwill only reduce maintainability by having you duplicate code. Also, YAGNI. Nov 7, 2012 at 9:45
  • 1
    @MichaelBorgwardt: Sure, but in that case, the standard API becomes the wrapper and you can swap libraries easily.
    – Blrfl
    Nov 7, 2012 at 21:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.