Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Por que testes de unidade não são suficientes para seus microsserviços

Por que testes de unidade não são suficientes para seus microsserviços

Sem dúvida a adoção de microsserviços possibilitou que empresas com dezenas ou centenas de times pudessem colocar software em produção de forma isolada e independente, em ritmos distintos sem que um time pisasse no pé do outro. Contudo, não podemos ignorar que apesar das vantagens organizacionais trazidas por esse estilo arquitetural, tivemos que abraçar sua complexidade inerente que, em essência, saiu do código e foi parar nas bordas.

O que eu quero dizer, é que mesmo pequenas lógicas de negócio deixaram de ser chamadas locais em memória dentro de um mesmo processo e passaram a ser chamadas remotas entre serviços numa rede instável por natureza. Garantir que estas lógicas funcionam como esperado deixou de ser uma tarefa simples, e confiar apenas nos testes de unidade pode ser perigoso e um erro sem volta.

Nesta palestra, pretendo discutir por que testes de unidade sozinhos não são adequados para garantir a corretude do seu código, nem para revelar bugs mais cedo ou mesmo para permitir a evolução da sua aplicação de forma segura e sustentável. Não à toa, vamos entender por que favorecer a escrita de testes de integração e abraçar as facilidades do seu framework IoC/DI pode ser crucial para o desenvolvimento, manutenção e entrega de qualidade dos seus microsserviços.

Se você confia que seus testes de unidade são suficientes, então essa palestra é para você, caro desenvolvedor(a).

(🎥 GRAVAÇÃO: https://youtu.be/ZV4Fl1uEbqw?si=PGDoPqkRvpR3MDhK)

Rafael Ponte

May 27, 2023
Tweet

More Decks by Rafael Ponte

Other Decks in Technology

Transcript

  1. Favoreça testes de integração …ou por que testes de unidade

    não são su fi cientes para seus microservices
  2. As vezes eu acho que muitos devs(as) estudam sobre testes

    tanto quanto estudam sobre Jira 😬
  3. — Martin Fowler “If my high level tests are fast,

    reliable, and cheap to modify - 
 then lower-level tests aren't needed.”
  4. “As long as you are focusing on fast, easy-to-be-written, with

    good feedback tests, you are fi ne.” https://e ff ectivesoftwaretesting.substack.com/p/unit-or-integration-tests
  5. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  6. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  7. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  8. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  9. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  10. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  11. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  12. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  13. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  14. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  15. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  16. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } } Injetado pelo Spring!
  17. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  18. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  19. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  20. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  21. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  22. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  23. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  24. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  25. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  26. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  27. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  28. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  29. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  30. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  31. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  32. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  33. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  34. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  35. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  36. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  37. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } } Mockito
  38. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  39. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } } when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false);
  40. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } } when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false);
  41. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } } when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false);
  42. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } } when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false);
  43. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } } when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false);
  44. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } } when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false);
  45. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } } when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false);
  46. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } } when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false);
  47. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  48. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  49. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  50. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  51. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", “Design e Arquitetura Java", LocalDate.now().plusDays(1)); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(false); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseEntity<?> response = controller.cadastra(request); // validação assertEquals(HttpStatus.CREATED, response.getStatusCode()); } }
  52. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  53. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  54. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  55. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  56. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  57. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  58. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  59. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  60. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  61. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  62. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  63. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  64. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  65. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  66. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  67. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  68. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  69. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  70. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } } when(repository.existsByIsbn(“978-0-4703-2225-3")).thenReturn(true);
  71. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } } when(repository.existsByIsbn(“978-0-4703-2225-3")).thenReturn(true);
  72. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } } when(repository.existsByIsbn(“978-0-4703-2225-3")).thenReturn(true);
  73. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } } when(repository.existsByIsbn(“978-0-4703-2225-3")).thenReturn(true);
  74. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } } when(repository.existsByIsbn(“978-0-4703-2225-3")).thenReturn(true);
  75. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } } when(/** ... */).thenReturn( ); true
  76. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  77. class NovoLivroControllerTest { @Test @DisplayName("deve cadastrar novo livro") public void

    t1() { /** ... */ } @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Outro livro de Arquitetura Java", LocalDate.now()); LivroRepository repository = mock(LivroRepository.class); when(repository.existsByIsbn("978-0-4703-2225-3")).thenReturn(true); // ação NovoLivroController controller = new NovoLivroController(repository); ResponseStatusException exception = assertThrows(ResponseStatusException.class, () -> { controller.cadastra(request); }); // validação assertEquals("livro já existente", exception.getReason()); } }
  78. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  79. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  80. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  81. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } } Desligamos a validação do Spring! 👀
  82. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  83. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  84. @Entity class Livro { @Id @GeneratedValue(strategy = IDENTITY) private Long

    id; private String isbn; private String titulo; private LocalDate publicadoEm; // construtor, getters etc }
  85. @Entity class Livro { @Id @GeneratedValue(strategy = IDENTITY) private Long

    id; private String isbn; private String titulo; private LocalDate publicadoEm; // construtor, getters etc }
  86. @Entity class Livro { @Id @GeneratedValue(strategy = IDENTITY) private Long

    id; private String isbn; private String titulo; private LocalDate publicadoEm; // construtor, getters etc }
  87. @Entity class Livro { @Id @GeneratedValue(strategy = IDENTITY) private Long

    id; private String isbn; private String titulo; private LocalDate publicadoEm; // construtor, getters etc }
  88. @Entity class Livro { @Id @GeneratedValue(strategy = IDENTITY) private Long

    id; private String isbn; private String titulo; private LocalDate publicadoEm; // construtor, getters etc }
  89. @Entity class Livro { @Id @GeneratedValue(strategy = IDENTITY) private Long

    id; private String isbn; private String titulo; private LocalDate publicadoEm; // construtor, getters etc }
  90. @Entity class Livro { @Id @GeneratedValue(strategy = IDENTITY) private Long

    id; private String isbn; private String titulo; private LocalDate publicadoEm; // construtor, getters etc }
  91. @Entity class Livro { @Id @GeneratedValue(strategy = IDENTITY) private Long

    id; private String isbn; private String titulo; private LocalDate publicadoEm; // construtor, getters etc }
  92. @Entity class Livro { @Id @GeneratedValue(strategy = IDENTITY) private Long

    id; private String isbn; private String titulo; private LocalDate publicadoEm; // construtor, getters etc }
  93. @Entity class Livro { @Id @GeneratedValue(strategy = IDENTITY) private Long

    id; private String isbn; private String titulo; private LocalDate publicadoEm; // construtor, getters etc }
  94. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  95. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  96. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  97. — Martin Fowler “If my high level tests are fast,

    reliable, and cheap to modify - 
 then lower-level tests aren't needed.”
  98. “As long as you are focusing on fast, easy-to-be-written, with

    good feedback tests, you are fi ne.” https://e ff ectivesoftwaretesting.substack.com/p/unit-or-integration-tests
  99. Favoreça testes de integração …ou por que testes de unidade

    não são su fi cientes para seus microservices
  100. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  101. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } }
  102. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } }
  103. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } }
  104. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } }
  105. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } }
  106. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } }
  107. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } }
  108. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } }
  109. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } }
  110. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } } // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated());
  111. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } } // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); @Autowired protected MockMvc mockMvc;
  112. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } } // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated());
  113. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } } // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated());
  114. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } } // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated());
  115. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } } // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated());
  116. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } } // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated());
  117. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } } // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated());
  118. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } } // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) );
  119. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } } // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated());
  120. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } } // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated());
  121. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } }
  122. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } }
  123. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } } Efeito colateral!
  124. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } }
  125. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } }
  126. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } }
  127. @SpringBootTest @ActiveProfiles("test") @AutoConfigureMockMvc(printOnlyOnFailure = false) class NovoLivroControllerIntegrationTest { @Autowired private

    LivroRepository repository; @Autowired protected MockMvc mockMvc; @Autowired private ObjectMapper mapper; @BeforeEach public void setUp() { repository.deleteAll(); } @Test @DisplayName("deve cadastrar novo livro") public void t1() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); // validação assertEquals(1, repository.count()); } }
  128. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // grava livro no banco repository.save(request.toModel()); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.detail", is("livro já existente”))); // validação assertEquals(1, repository.count()); } }
  129. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // grava livro no banco repository.save(request.toModel()); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.detail", is("livro já existente”))); // validação assertEquals(1, repository.count()); } }
  130. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // grava livro no banco repository.save(request.toModel()); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.detail", is("livro já existente”))); // validação assertEquals(1, repository.count()); } }
  131. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // grava livro no banco repository.save(request.toModel()); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.detail", is("livro já existente”))); // validação assertEquals(1, repository.count()); } }
  132. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // grava livro no banco repository.save(request.toModel()); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.detail", is("livro já existente”))); // validação assertEquals(1, repository.count()); } }
  133. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // grava livro no banco repository.save(request.toModel()); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.detail", is("livro já existente”))); // validação assertEquals(1, repository.count()); } }
  134. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // grava livro no banco repository.save(request.toModel()); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.detail", is("livro já existente”))); // validação assertEquals(1, repository.count()); } }
  135. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // grava livro no banco repository.save(request.toModel()); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.detail", is("livro já existente”))); // validação assertEquals(1, repository.count()); } }
  136. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // grava livro no banco repository.save(request.toModel()); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.detail", is("livro já existente”))); // validação assertEquals(1, repository.count()); } }
  137. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // grava livro no banco repository.save(request.toModel()); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.detail", is("livro já existente”))); // validação assertEquals(1, repository.count()); } }
  138. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando livro já existente") public void t2() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // grava livro no banco repository.save(request.toModel()); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.detail", is("livro já existente”))); // validação assertEquals(1, repository.count()); } }
  139. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  140. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  141. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } } Validação!
  142. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  143. public class NovoLivroRequest { @ISBN @NotBlank private String isbn; @NotBlank

    private String titulo; @Past @NotNull private LocalDate publicadoEm; // construtor, getters etc }
  144. public class NovoLivroRequest { @ISBN @NotBlank private String isbn; @NotBlank

    private String titulo; @Past @NotNull private LocalDate publicadoEm; // construtor, getters etc }
  145. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  146. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  147. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  148. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  149. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  150. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  151. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  152. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  153. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  154. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  155. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  156. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  157. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  158. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  159. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  160. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  161. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  162. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  163. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  164. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } } Desligamos a validação do Spring! 👀
  165. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  166. class NovoLivroControllerIntegrationTest { // atributos, outros métodos de teste e

    @BeforeEach @Test @DisplayName("não deve cadastrar novo livro quando parametros invalidos") public void t3() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( “978-0-INVA-LID-XX", "", LocalDate.now().plusDays(1) ); // ação String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.violations", hasSize(3))) .andExpect(jsonPath("$.violations", containsInAnyOrder( violation("isbn", "invalid ISBN"), violation("titulo", "must not be blank"), violation("publicadoEm", "must be a past date") ) )); // validação assertEquals(0, repository.count()); } }
  167. @Entity class Livro { @Id @GeneratedValue(strategy = IDENTITY) private Long

    id; private String isbn; private String titulo; private LocalDate publicadoEm; // construtor, getters etc }
  168. @Entity class Livro { @Id @GeneratedValue(strategy = IDENTITY) private Long

    id; private String isbn; private String titulo; private LocalDate publicadoEm; // construtor, getters etc }
  169. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  170. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }
  171. Aplicação Usuário 1 Usuário 2 POST /api/livros { isbn: “ABC-123”,

    titulo: “Livro X”, publicadoEm: “2023-01-01” }
  172. Aplicação Usuário 1 Usuário 2 POST /api/livros { isbn: “ABC-123”,

    titulo: “Livro X”, publicadoEm: “2023-01-01” } POST /api/livros { isbn: “ABC-123”, titulo: “Livro X”, publicadoEm: “2023-01-01” }
  173. Aplicação Usuário 1 Usuário 2 HTTP 201 (CREATED) POST /api/livros

    { isbn: “ABC-123”, titulo: “Livro X”, publicadoEm: “2023-01-01” } POST /api/livros { isbn: “ABC-123”, titulo: “Livro X”, publicadoEm: “2023-01-01” }
  174. Aplicação Usuário 1 Usuário 2 HTTP 201 (CREATED) HTTP 201

    (CREATED) POST /api/livros { isbn: “ABC-123”, titulo: “Livro X”, publicadoEm: “2023-01-01” } POST /api/livros { isbn: “ABC-123”, titulo: “Livro X”, publicadoEm: “2023-01-01” }
  175. ID ISBN TITULO PUBLICADO_EM 1001 ... ... ... 1002 ABC-123

    Livro X 2023-01-01 1003 ABC-123 Livro X 2023-01-01 1004 ... ... ...
  176. ID ISBN TITULO PUBLICADO_EM 1001 ... ... ... 1002 ABC-123

    Livro X 2023-01-01 1003 ABC-123 Livro X 2023-01-01 1004 ... ... ...
  177. class NovoLivroControllerIntegrationTest { // atributos @Test @DisplayName("não deve cadastrar novo

    livro repetido quando em alta-concorrência") public void t4() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação doSyncAndConcurrently(10, s -> { String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); }); // validação assertEquals(1, repository.count()); } }
  178. class NovoLivroControllerIntegrationTest { // atributos @Test @DisplayName("não deve cadastrar novo

    livro repetido quando em alta-concorrência") public void t4() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação doSyncAndConcurrently(10, s -> { String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); }); // validação assertEquals(1, repository.count()); } }
  179. class NovoLivroControllerIntegrationTest { // atributos @Test @DisplayName("não deve cadastrar novo

    livro repetido quando em alta-concorrência") public void t4() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação doSyncAndConcurrently(10, s -> { String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); }); // validação assertEquals(1, repository.count()); } }
  180. class NovoLivroControllerIntegrationTest { // atributos @Test @DisplayName("não deve cadastrar novo

    livro repetido quando em alta-concorrência") public void t4() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação doSyncAndConcurrently(10, s -> { String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); }); // validação assertEquals(1, repository.count()); } }
  181. class NovoLivroControllerIntegrationTest { // atributos @Test @DisplayName("não deve cadastrar novo

    livro repetido quando em alta-concorrência") public void t4() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação doSyncAndConcurrently(10, s -> { String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); }); // validação assertEquals(1, repository.count()); } }
  182. class NovoLivroControllerIntegrationTest { // atributos @Test @DisplayName("não deve cadastrar novo

    livro repetido quando em alta-concorrência") public void t4() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação doSyncAndConcurrently(10, s -> { String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); }); // validação assertEquals(1, repository.count()); } }
  183. class NovoLivroControllerIntegrationTest { // atributos @Test @DisplayName("não deve cadastrar novo

    livro repetido quando em alta-concorrência") public void t4() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação doSyncAndConcurrently(10, s -> { String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); }); // validação assertEquals(1, repository.count()); } } Número de usuários concorrentes!
  184. class NovoLivroControllerIntegrationTest { // atributos @Test @DisplayName("não deve cadastrar novo

    livro repetido quando em alta-concorrência") public void t4() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação doSyncAndConcurrently(10, s -> { String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); }); // validação assertEquals(1, repository.count()); } }
  185. class NovoLivroControllerIntegrationTest { // atributos @Test @DisplayName("não deve cadastrar novo

    livro repetido quando em alta-concorrência") public void t4() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação doSyncAndConcurrently(10, s -> { String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); }); // validação assertEquals(1, repository.count()); } }
  186. class NovoLivroControllerIntegrationTest { // atributos @Test @DisplayName("não deve cadastrar novo

    livro repetido quando em alta-concorrência") public void t4() throws Exception { // cenário NovoLivroRequest request = new NovoLivroRequest( "978-0-4703-2225-3", "Design e Arquitetura Java", LocalDate.now().minusMonths(6) ); // ação doSyncAndConcurrently(10, s -> { String json = toJson(request); mockMvc.perform(post("/api/livros") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isCreated()); }); // validação assertEquals(1, repository.count()); } }
  187. @Entity class Livro { @Id @GeneratedValue(strategy = IDENTITY) private Long

    id; private String isbn; private String titulo; private LocalDate publicadoEm; // construtor, getters etc }
  188. @Entity class Livro { @Id @GeneratedValue(strategy = IDENTITY) private Long

    id; private String isbn; private String titulo; private LocalDate publicadoEm; // construtor, getters etc }
  189. @Entity class Livro { @Id @GeneratedValue(strategy = IDENTITY) private Long

    id; @Column(unique = true) private String isbn; private String titulo; private LocalDate publicadoEm; // construtor, getters etc }
  190. “As long as you are focusing on fast, easy-to-be-written, with

    good feedback tests, you are fi ne.” https://e ff ectivesoftwaretesting.substack.com/p/unit-or-integration-tests
  191. @RestController public class NovoLivroController { private final LivroRepository repository; @Transactional

    @PostMapping("/api/livros") public ResponseEntity<?> cadastra(@RequestBody @Valid NovoLivroRequest request) { if (repository.existsByIsbn(request.getIsbn())) { throw new ResponseStatusException(UNPROCESSABLE_ENTITY, “livro já existente”); } Livro livro = request.toModel(); repository.save(livro); return ResponseEntity .status(CREATED).build(); } }