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:
- 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 wrapsZend_Mail
which is already unit tested by the Zend team. Is there a better approach to all this? Zend_Mail
'ssend()
function could actually have aZend_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