Po godzinach zacząłem pisać sobie prosty projekt w TDD, naszła mnie jednak pewna refleksja przy pisaniu testów do update'u jakiegoś obiektu.
Do sprawdzenia jest kilka przypadków, wszystko walidowane przez wydzieloną do tego klasę wołaną z głównego serwisu
-czy wszystkie pola nie są nullem / pustym stringiem
-czy jedna z wartości liczbowych jest większa od 0
-czy jeden z ciagów znaków nie przekracza 1024 znaków
-czy podany id w ogóle istnieje
W prawdziwym przypadku wyszło ponad 10 testów jednostkowych, klasa testowa była kilka razy większa od właściwej implementacji. Dodatkowo doszło pisanie interfejsu dla repository i jego implementacji InMemory. Po czasie jednak się zorientowałem, że ta metoda będzie i tak wołana tylko przez http - dorzuciłem więc kilka adnotacji javax.validation.constraints
do wejściowego dtosa i w efekcie mogłem wywalić całą klasę odpowiednią za walidację i 3/4 testów jednostkowych. Implementacja na tę chwilę wygląda mniej więcej tak
@Builder
@Getter
public class UpdateItemRequest {
@NotBlank
private final String itemId;
@NotBlank
@Size(max = 1024)
private final String description;
@NotBlank
@Size(min = 0)
private final Integer quantity;
}
@RestController
class ItemController {
@PutMapping
ResponseEntity<Item> updateItem(@RequestBody @Valid UpdateItemRequest request) {
return ResponseEntity.ok(itemService.updateItem(request));
}
}
@Service
public class ItemService {
Item updateItem(UpdateItemRequest request) {
return itemRepository.findById(request.getItemId())
.map(item -> update(item, request))
.orElseThrow(() -> new RuntimeException("Item not found"));
}
}
No i teraz pytanie - czy jest sens takie operacje testować jednostkowo?
Czy taki test na bazie InMemory w ogóle ma jakąś wartość?
Czy sam test integracyjny nie byłby tutaj całkowicie wystarczający?
Czy w ogóle podejście TDD ma tutaj sens - sama idea mówi by te testy odpalać praktycznie co chwila, jeżeli miałbym co chwile czekać aż uruchomi się Spring to z miejsca bym zrezygnowal z ich pisania.
No i jeżeli zdecyduje się na pozostanie tylko przy testach integracyjnych - czy warto w nich sprawdzać case typu ujemne quantity, description na więcej niż 1024 znaki czy np. czy @ControllerAdvice złapie moj wyjątek? Czy olać sprawdzanie frameworka i napisać test na happy path?