Should library classes be wrapped before using them in unit testing?

Posted by Songo on Programmers See other posts from Programmers or by Songo
Published on 2012-11-05T21:35:51Z Indexed on 2012/11/05 23:18 UTC
Read the original article Hit count: 229

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.

Example:

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.

Does that mean that I can never use a library class directly and must always wrap it in a class of my own?

Example:

interface Mailer{
    public function setTo($to);
    public function setSubject($subject);
    public function setBody($body);
    public function send();
}

class MyMailer implements Mailer{
    private $mailer;
    function __construct(){
            $this->mail=new Zend_Mail; //The class isn't injected this time
        }
    function setTo($to){
        $this->mailer->setTo($to);
    }
    //implement the rest of the interface functions similarly
}

And now my Logger class can be happy :D

class Logger{
        private $mailer;    
        function __construct(Mailer $mail){
            $this->mail=$mail;
        }
    //rest of the code unchanged
}

Questions:

  1. Although I solved the mocking problem by introducing an interface, I have created a totally new class Mailer that now needs to be unit tested although it only wraps Zend_Mail which is already unit tested by the Zend team. Is there a better approach to all this?
  2. Zend_Mail's send() function could actually have a Zend_Transport object when called (i.e. public function send($transport = null)). Does this make the idea of a wrapper class more appealing?

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

© Programmers or respective owner

Related posts about design

Related posts about object-oriented