Ist das Einwickeln eines Drittanbieter-Codes die einzige Lösung, um seine Verbraucher einem Unit-Test zu unterziehen?

13

Ich mache Unit-Tests und in einer meiner Klassen muss ich eine Mail von einer der Methoden senden, also füge ich mit Hilfe der Konstruktorinjektion eine Instanz der Zend_MailKlasse ein, die im Zend-Framework ist.

Nun argumentieren einige Leute, wenn eine Bibliothek stabil genug ist und sich nicht oft ändert, besteht keine Notwendigkeit, sie zu verpacken. Vorausgesetzt, das Zend_Mailist stabil und ändert sich nicht und es passt sich meinen Bedürfnissen an, dann brauche ich keinen Wrapper dafür.

Schauen Sie sich jetzt meine Klasse an Logger, die davon abhängt 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
   }        
}

Beim Unit-Test muss jedoch jeweils eine Komponente getestet werden, sodass ich mich über die Zend_MailKlasse lustig machen muss . Außerdem verstoße ich gegen das Prinzip der Abhängigkeitsinversion , da meine LoggerKlasse jetzt von Konkretion und nicht von Abstraktion abhängt.

Wie kann ich nun Loggerisoliert testen, ohne zu verpacken Zend_Mail?

Der Code ist in PHP, aber Antworten müssen nicht sein. Dies ist eher ein Designproblem als eine sprachspezifische Funktion

Songo
quelle
Müssen Sie eine Schnittstelle verwenden? Unterstützt PHP nicht Duck Typing?
Kevin Cline
@kevincline Nun, ich habe PHP verwendet, weil es die Sprache ist, die ich am häufigsten verwende, aber ich suche tatsächlich eine allgemeine Lösung für das Problem, die nicht nur auf PHP beschränkt ist.
Songo

Antworten:

21

Sie möchten immer Typen und Methoden von Drittanbietern hinter einer Schnittstelle einschließen. Dies kann mühsam und schmerzhaft sein. Manchmal können Sie einen Codegenerator schreiben oder ein Tool verwenden, um dies zu tun.

Aber seien Sie nicht versucht, die Bibliotheksmethoden oder -typen im gesamten Code zu verwenden. Zunächst werden Sie Probleme haben, Komponententests zu schreiben. Dann ändert sich eine Lizenz, oder Sie möchten zu einer Plattform gehen, die nicht von einem Drittanbieter unterstützt wird, und Sie werden feststellen, dass diese Typen und Abhängigkeiten in und um alle Ihre anderen Klassen gewebt haben.

Die Möglichkeit, Drittanbieter schnell zu wechseln, ist ein enormer Vorteil.

Ben
quelle
4
"Alles was nicht von dir geschrieben wurde" ist ein bisschen viel. Bibliotheken, die Teil des Standards oder der Plattform sind, sind schwer zu verpacken. Sie möchten wahrscheinlich nicht alle .NET-Komponenten umbrechen. Wenn die Wrapper nur Schnittstellen durchlaufen oder generierter Code sind, habe ich beim Schreiben von Tests wenig Nutzen gefunden. Wenn Logik vorhanden ist (Zusammenführen von Aufrufen usw.), können Tests hilfreich sein.
Ben
3
Upvoted für den letzten Satz.
Blrfl
1
Bei ordnungsgemäßer Umgestaltung wird jede wiederholte Nutzung der Bibliothekseinrichtungen in eine Serviceklasse zerlegt. Sie müssen es nicht im Voraus definieren.
Kevin Cline
3
-1: Außer in Fällen, in denen die Bibliothek eines Drittanbieters einen Dienst bereitstellt, für den es eine standardisierte API gibt, ist dies eine enorme Zeitverschwendung und mindert nur die Wartbarkeit, indem Sie Code duplizieren. Auch YAGNI.
Michael Borgwardt
1
@MichaelBorgwardt: Sicher, aber in diesem Fall wird die Standard-API zum Wrapper und Sie können Bibliotheken einfach austauschen.
Blrfl