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
-
Do you have to use an interface? Doesn't PHP support duck typing?kevin cline– kevin cline11/05/2012 22:42:23Commented 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– Songo11/05/2012 22:53:02Commented Nov 5, 2012 at 22:53
1 Answer 1
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.
-
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– Ben11/05/2012 22:14:55Commented Nov 5, 2012 at 22:14
-
4
-
1If you refactor properly, any repetitive use of library facilities will be factored out into a service class. No need to define it up front.kevin cline– kevin cline11/05/2012 22:42:02Commented 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.Michael Borgwardt– Michael Borgwardt11/07/2012 09:45:26Commented 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– Blrfl11/07/2012 21:42:19Commented Nov 7, 2012 at 21:42
Explore related questions
See similar questions with these tags.