Skip to content

Instantly share code, notes, and snippets.

@teklakct
Last active March 15, 2021 07:54
Show Gist options
  • Save teklakct/3ad0069aa1d4d4c6579eeaa58db58dad to your computer and use it in GitHub Desktop.
Save teklakct/3ad0069aa1d4d4c6579eeaa58db58dad to your computer and use it in GitHub Desktop.
Jak otestować wysyłanie SMS

Jak testować wysyłanie SMS?

Samego wysyłania SMSów jako taki calli do API proponuje nie testować automatycznie, a na pewno nie jednostkową. Jest tu dużo rzeczy tj, HTPP czy samo API providera, których nie ma co testować i mogą działać "różnie" w różnych warunkach. Samo wysyłanie API możesz przetestować e2e lub nawet manualnie (tak będzie najłatwiej przeczytać SMS i sprawdzić czy dotarł). Lepiej otestować to jak Twój system komunikuje się z "czymś" do wysyłania SMSów, jak tworzonę są wiadomości (to nie jest odpowiedzialność usługi do wysyłania SMS, więc musisz ją wydzielić poza tą klase).

How to do it?

Wrzucam Ci "pseudocode", na którym chciałbym Ci pokazać jakie mam podejście do tego typu tematu. Już plików od testów nie dodawałem bo przy takim kodzi to będzie turbo proste. Kiedyś miałem podobny problem w projekcie do którego wszedłem i z biegem czasu trzeba było to poprawić.

Context background

Kiedyś w projekcie zastałem kod, podobny do tego który opisujesz. Oczywiście nazywał się MessageService, i robił zdecydowanie za dużo:

  • przygotowywał wiadomości
  • pobierał odbiorców z bazki i ich nr telefonów
  • wysyłał wiadomości na te podane sms
  • i jeszcze inne

Na początku przyjąłem zasadę

jak 💩 leży i nie śmierdzi to nie dotykać,

Z czasem okazało się, że ten provider który jest używany jest drogi i chcą wymienić na tańszy. Tak też zrefactorowałem to do czegoś na wzór tego co masz powyżej. Wydzieliłem iterfejs dla sms providera. Generowanie treści SMS poszło tam gdzie to miało sens. Usunąłem repo itd, i pobieranie nr telefonu do wysyłki było w miejscu gdzie wykorzystywany był ten provider, bo i po co sms providerowi wiedzieć o jakiś obiektach Twojego systemu.

Zalety:

  • masz interfejs, który łatwo możesz mockować w miejscach gdzie testujesz wysyłanie SMSow ale nie jest Ci potrzebne
  • wydzielając intererjs od razu widać, że przygotowanie wiadomości musi iść do innego serwisu, odpowiedzialności SmsProvidera w ramach tej aplikacji to tylko send
  • podmiana providera na nowy to tylko napisanie nowej implementacji i podmiana serwisu w kontenerze
  • integracyjnie, o ile musisz testujesz tylko konkretne implementacje SmsProvidera lub zostawiasz to na testy manualne
  • mozesz mieć kilku smsproviderow i zrobic jakiś chain by być pewnym, że sms poleciał (wtedy trzeba by dać jakis response do send albo rzucac wyjątki (is up to you)
  • szacun na dzielni ;)
<?php
// gdzies w aplikacji gdzie korzystasz z wysylania emaili
(...)
function whereINeedToSendSMS(): void
{
$phoneNumber = $receiver->getPhoneNumber();
$message = $this->smsFactory->prepareMessage(Order $order);
$this->smsProvider->send($phoneNumber, $message);
(...)
}
<?php
// Jak lubisz klasyczne podejście (gdy nie chcesz mockować) to się przyda tylko do testów, jak jednak londyńską szkołę to po prostu mockuj `SmsProvider`
final class PersistenDummySmsProvider implements SmsProvider
{
private array $messages = [];
public function send(string $phoneNumber, string $message): void
{
$this->messages[$phone][] = $message;
}
// ta funkcja jest używana w testach
public function getMessagesSent(): array
{
return $this->messages;
}
}
<?php
final class RealSmsProvider implements SmsProvider
{
public function send(string $phoneNumber, string $message)
{
// cala logika zwiazana z wysylanie przez API providera
}
}
<?php
interface SmsProvider
{
public function send(string $phoneNumber, string $message): void;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment