Jak mogę przetestować jednostkę moją usługę REST?

16

Jestem nowy w testowaniu jednostkowym, mam jedną metodę internetową REST, która po prostu wywołuje DB i wypełnia DTO. Pseudo kod to

public object GetCustomer(int id)
{
  CustomerDTO objCust = //get from DB
  return objCust;
}

Mam wątpliwości, jak napisać testy dla tych metod i rodzaj testów (integracja / jednostka), które należy uwzględnić. A w przypadku testów jednostkowych musi trafić w DB. Gdyby tak było i przekazałbym identyfikator klienta i nie wykonałem kilku zapewnień, dane mogłyby się ostatecznie zmienić, powodując awarie.

Myślę, że brakuje mi czegoś, co rozumie te pojęcia.

Słoneczny
źródło
5
W opublikowanym kodzie rzeczy do przetestowania to: (1) Czy możesz wywołać GetCustomer z parametrem int jako parametrem. (2) Czy zwraca obiekt CustomerDTO? (3) Czy ten obiekt został zapełniony z bazy danych zgodnie z oczekiwaniami? (4) Czy oczekiwane zachowanie występuje, jeśli zostanie wywołane z int, który nie odpowiada ważnemu klientowi? Nie ma to jeszcze nic wspólnego z REST. Gdy będziesz gotowy napisać kod odpowiadający na żądania RESTful, napiszesz dla niego testy.
DavidO
@DavidO: „Czy ten obiekt został zapełniony z bazy danych zgodnie z oczekiwaniami?” zdecydowanie nie jest testem jednostkowym (w odniesieniu do kodu OP). To test integracyjny.
Flater
Tak, masz rację. Gdybym mógł cofnąć się i zmienić komentarz, aby wspomniał, że w teście integracji zweryfikowałbyś komponent DB, a w innym przypadku wyśmiewałby go, dokonałbym tej edycji, ale okno edycji dla komentarzy, jeśli 5 minut, a komentarz został zrobiony sześć Lata temu. :)
DavidO

Odpowiedzi:

18

Podczas testów jednostkowych nie oczekuje się, że przeprowadzisz testy z bazą danych, a przynajmniej z bazą danych, której nie przygotowałeś do testów jednostkowych. Testowanie z bazą danych, a tym samym testowanie różnych warstw aplikacji w tym samym czasie, jest ogólnie postrzegane jako test integracji . W testach jednostkowych powinieneś testować tylko to, co robi twoja metoda, co zwraca w zależności od różnych parametrów, i kiedy (lub nie) powinna zawieść.

Oczekuje się, że w metodzie wykonujesz wywołania metod X z innych klas. Nie testujesz tych metod X , więc musisz wyśmiewać te metody.

Przypuszczam, że piszesz swój kod w Javie, w takim przypadku masz świetne frameworki, takie jak Mockito, które mogą być dla ciebie pomocne. Niezależnie od tego, czy używasz kpiny, czy nie, wybierasz, że zaoszczędzą ci dużo czasu, a ten, o którym wspomniałem, nie jest tak naprawdę skomplikowany.

Jeśli chcesz po prostu napisać własną próbę eksperymentalną, załóż, że masz następującą CustomerRepositoryklasę:

public class CustomerRepository {
 public CustomerDTO getCustomer(int id) {
   ...
 }
}

Możesz napisać własną kpiącą i brudną CustomerRepositoryklasę w następujący sposób:

public class MockedCustomerRepository extends CustomerRepository {
 public boolean bThrowDatabaseException;
 public boolean bReturnNull;
 public boolean bReturnCustomerWrongId;
 public boolean bReturnCustomerWithId;
 public CustomerDTO getCustomer(int id) {
  if(bThrowDatabaseException) { 
    throw new DatabaseException("xxx"); 
  } else if(bReturnNull) { 
    return null; 
  } else if(bReturnCustomerWrongId) { 
    throw new CustomerNotExistException(id);
  } else if(bReturnCustomerWithId) { 
    return new CustomerDTO(id); 
  }
 }
}

Następnie w przypadku testowym zasadniczo zastępujesz swoje „standardowe” wystąpienie CustomerRepository na fałszywe wystąpienie, które pozwoli ci przetestować metodę pod kątem różnych wyników getCustomer:

public class CustomerRestTest {
  public void testGetCustomer_databaseFailure() {
    MockedCustomerRepository dto = new MockedCustomerRepository();
    dto.bThrowDataBaseException = true;
    yRestClass rest = new MyRestClass();
    rest.dto = dto;
    rest.getCustomer(0);
    // depending on what you do in your getCustomer method, you should check if you catched the exception, or let it pass, etc.. Make your assertions here

  public void testGetCustomer_customerNotExist() {
    // etc.
  }
}

Zasadniczo każda metoda testowa powinna testować tylko jedno, co pomaga utrzymać małe testy i koncentrować się na jednym zadaniu.

Powtórzę :-) Pisanie całej szydzonej klasy zajmuje trochę czasu. Zastanów się nad użyciem frameworku, im mniej ktoś pisze kod, tym mniej błędów popełnia , prawda? Wyśmiewanie metody, która zgłasza wyjątek lub zwraca określoną wartość dla danego parametru, jest bułką z masłem i zajmuje 2 lub 3 wiersze (przynajmniej z mockito)

Mam nadzieję, że pomaga to w testowaniu metody REST.

Jalayn
źródło
4
Zwykle nie masz logiki w swoich klasach DTO, szczególnie tych, które współdziałają z twoim przechowywaniem danych.
JustAnotherUserYouMayKnowOrNot
1
To był tylko przykład, ale masz całkowitą rację. Zamierzam zmienić przykłady, aby lepiej pasowały do ​​teorii.
Jalayn