Czy pakowanie kodu strony trzeciej jest jedynym rozwiązaniem do testowania jednostkowego konsumentów?

13

Robię testy jednostkowe i na jednej z moich klas muszę wysłać wiadomość e-mail z jednej z metod, więc za pomocą wstrzykiwania konstruktora wstrzykuję instancję Zend_Mailklasy, która jest w środowisku Zend.

Teraz niektórzy twierdzą, że jeśli biblioteka jest wystarczająco stabilna i nie zmienia się często, nie trzeba jej owijać. Zakładając, że Zend_Mailjest stabilny i nie ulegnie zmianie i całkowicie odpowiada moim potrzebom, nie będę potrzebował opakowania.

Teraz spójrz na moją klasę, Loggerktóra zależy od 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
   }        
}

Jednak testy jednostkowe wymagają testowania jednego elementu na raz, więc muszę wyśmiewać Zend_Mailklasę. Ponadto naruszam zasadę odwrócenia zależności, ponieważ moja Loggerklasa zależy teraz od konkrecji, a nie abstrakcji.

Jak mogę teraz testować Loggerw izolacji bez opakowania Zend_Mail?

Kod jest w PHP, ale odpowiedzi nie muszą być. Jest to raczej kwestia projektu niż funkcja specyficzna dla języka

Songo
źródło
Czy musisz korzystać z interfejsu? Czy PHP nie obsługuje pisania kaczego?
kevin cline
@ kevincline dobrze używałem PHP, ponieważ jest to język, którego używam najczęściej, ale tak naprawdę szukam ogólnego rozwiązania problemu nie ograniczonego tylko do PHP.
Songo,

Odpowiedzi:

21

Zawsze chcesz zawijać typy i metody stron trzecich za interfejsem. Może to być nudne i bolesne. Czasami możesz napisać generator kodu lub użyć do tego narzędzia.

Ale nie ulegaj pokusie używania metod lub typów bibliotecznych w całym kodzie. Na początek będziesz miał problemy z pisaniem testów jednostkowych. Następnie licencja ulegnie zmianie lub będziesz chciał przejść na platformę nieobsługiwaną przez stronę trzecią, a przekonasz się, że te typy i zależności wplątały się we wszystkie pozostałe klasy.

Ogromną zaletą jest możliwość szybkiej zmiany zewnętrznych dostawców.

Ben
źródło
4
„Wszystko, co nie zostało napisane przez ciebie” to trochę za dużo. Biblioteki wchodzące w skład standardu lub platformy są trudne do zawinięcia. Prawdopodobnie nie chcesz na przykład owijać wszystkich komponentów .NET. Jeśli opakowania są po prostu przekazywane przez interfejsy lub są generowane, nie ma żadnej korzyści z pisania testów. Jeśli jest tam logika (łączenie połączeń itp.), Testy mogą być pomocne.
Ben
3
Głosowano na ostatnie zdanie.
Blrfl,
1
Jeśli dokonujesz poprawnej refaktoryzacji, każde powtarzające się korzystanie z udogodnień bibliotecznych zostanie uwzględnione w klasie usług. Nie ma potrzeby definiowania go z góry.
kevin cline
3
-1: Z wyjątkiem przypadków, w których biblioteka innej firmy zapewnia usługę, dla której istnieje znormalizowany interfejs API, jest to ogromna strata czasu i tylko ograniczy konserwowalność poprzez duplikowanie kodu. Również YAGNI.
Michael Borgwardt,
1
@MichaelBorgwardt: Jasne, ale w takim przypadku standardowy interfejs API staje się opakowaniem i możesz łatwo zamieniać biblioteki.
Blrfl,