Should library classes be wrapped before using them in unit testing?
- by Songo
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:
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?
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