diff --git a/010_spring_boot/api_rest/api3/pom.xml b/010_spring_boot/api_rest/api3/pom.xml
index 6fd7037..17b51b7 100644
--- a/010_spring_boot/api_rest/api3/pom.xml
+++ b/010_spring_boot/api_rest/api3/pom.xml
@@ -1,105 +1,111 @@
- 4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 3.1.3
-
-
- med.voll
- api
- 0.0.1-SNAPSHOT
- api
- API Rest para clínica Voll
-
- 17
-
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-devtools
- runtime
- true
-
-
- org.projectlombok
- lombok
- true
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.1.3
+
+
+ med.voll
+ api
+ 0.0.1-SNAPSHOT
+ api
+ API Rest para clínica Voll
+
+ 17
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+ true
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
-
- org.springframework.boot
- spring-boot-starter-data-jpa
-
-
- org.flywaydb
- flyway-core
-
-
- org.flywaydb
- flyway-mysql
-
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.flywaydb
+ flyway-core
+
+
+ org.flywaydb
+ flyway-mysql
+
-
- com.mysql
- mysql-connector-j
- runtime
-
+
+ com.mysql
+ mysql-connector-j
+ runtime
+
-
- org.springframework.boot
- spring-boot-starter-validation
-
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
-
- org.springframework.boot
- spring-boot-starter-security
-
-
- org.springframework.security
- spring-security-test
- test
-
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.security
+ spring-security-test
+ test
+
-
- com.auth0
- java-jwt
- 4.4.0
-
+
+ com.auth0
+ java-jwt
+ 4.4.0
+
-
- org.springdoc
- springdoc-openapi-starter-webmvc-ui
- 2.2.0
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
- org.projectlombok
- lombok
-
-
-
-
-
-
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 2.2.0
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
diff --git a/010_spring_boot/api_rest/api3/src/main/java/med/voll/api/controller/AutenticacionController.java b/010_spring_boot/api_rest/api3/src/main/java/med/voll/api/controller/AutenticacionController.java
index 53d93ba..7b56f59 100644
--- a/010_spring_boot/api_rest/api3/src/main/java/med/voll/api/controller/AutenticacionController.java
+++ b/010_spring_boot/api_rest/api3/src/main/java/med/voll/api/controller/AutenticacionController.java
@@ -1,5 +1,6 @@
package med.voll.api.controller;
+import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import med.voll.api.domain.usuario.DatosAutenticacionUsuario;
import med.voll.api.domain.usuario.Usuario;
@@ -17,6 +18,7 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/login")
+@Tag(name = "Autenticacion", description = "Provee token para usuario, que da acceso a otros endpoints")
public class AutenticacionController {
@Autowired
diff --git a/010_spring_boot/api_rest/api3/src/main/java/med/voll/api/controller/ConsultaController.java b/010_spring_boot/api_rest/api3/src/main/java/med/voll/api/controller/ConsultaController.java
index b936284..09a8a1a 100644
--- a/010_spring_boot/api_rest/api3/src/main/java/med/voll/api/controller/ConsultaController.java
+++ b/010_spring_boot/api_rest/api3/src/main/java/med/voll/api/controller/ConsultaController.java
@@ -1,5 +1,6 @@
package med.voll.api.controller;
+import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import jakarta.validation.Valid;
import med.voll.api.domain.consulta.AgendaDeConsultaService;
@@ -26,6 +27,7 @@ public class ConsultaController {
@PostMapping
@Transactional // ojo de donde se importa esta anotación
+ @Operation(summary = "Registra una consulta en la base de datos")
public ResponseEntity agendar(@RequestBody @Valid DatosAgendarConsulta datos) {
System.out.println(datos);
var response = service.agendar(datos);
@@ -34,6 +36,7 @@ public class ConsultaController {
}
@GetMapping
+ @Operation(summary = "Retorna listado de consultas")
public ResponseEntity> listar(
@PageableDefault(size = 10, sort = {"fecha"}) Pageable paginacion) {
var response = service.consultar(paginacion);
@@ -42,6 +45,7 @@ public class ConsultaController {
@DeleteMapping
@Transactional
+ @Operation(summary = "Cancela una consulta")
public ResponseEntity cancelar(@RequestBody @Valid DatosCancelarConsulta dados) {
service.cancelar(dados);
return ResponseEntity.noContent().build();
diff --git a/010_spring_boot/api_rest/api3/src/main/java/med/voll/api/controller/MedicoController.java b/010_spring_boot/api_rest/api3/src/main/java/med/voll/api/controller/MedicoController.java
index cd5a9eb..ad503a8 100644
--- a/010_spring_boot/api_rest/api3/src/main/java/med/voll/api/controller/MedicoController.java
+++ b/010_spring_boot/api_rest/api3/src/main/java/med/voll/api/controller/MedicoController.java
@@ -1,5 +1,6 @@
package med.voll.api.controller;
+import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import jakarta.transaction.Transactional;
import jakarta.validation.Valid;
@@ -24,6 +25,7 @@ public class MedicoController {
private MedicoRepository medicoRepository;
@PostMapping
+ @Operation(summary = "Registra un nuevo medico en la base de datos")
public ResponseEntity registrarMedico(
@RequestBody @Valid DatosRegistroMedico datosRegistroMedico,
UriComponentsBuilder uriComponentsBuilder) {
@@ -36,6 +38,7 @@ public class MedicoController {
}
@GetMapping
+ @Operation(summary = "Retorna listado de medicos")
public ResponseEntity> listadoMedicos(
@PageableDefault(size = 5) Pageable paginacion) {
return ResponseEntity.ok(medicoRepository.findByActivoTrue(paginacion).map(DatosListadoMedicos::new));
@@ -43,6 +46,7 @@ public class MedicoController {
@PutMapping
@Transactional
+ @Operation(summary = "Actualiza los datos de un medico existente")
public ResponseEntity actualizarMedico(
@RequestBody @Valid DatosActualizarMedico datosActualizarMedico) {
Medico medico = medicoRepository.getReferenceById(datosActualizarMedico.id());
@@ -55,6 +59,7 @@ public class MedicoController {
@DeleteMapping("/{id}")
@Transactional
+ @Operation(summary = "Cambia el estado de un medico a inactivo")
public ResponseEntity eliminarMedico(@PathVariable Long id) {
Medico medico = medicoRepository.getReferenceById(id);
medico.desactivarMedico();
@@ -62,6 +67,7 @@ public class MedicoController {
}
@GetMapping("/{id}")
+ @Operation(summary = "Retorna los registros del medico según Id")
public ResponseEntity retornaDatosMedico(@PathVariable Long id) {
Medico medico = medicoRepository.getReferenceById(id);
DatosRespuestaMedico datosRespuestaMedico = new DatosRespuestaMedico(
diff --git a/010_spring_boot/api_rest/api3/src/main/java/med/voll/api/controller/PacienteController.java b/010_spring_boot/api_rest/api3/src/main/java/med/voll/api/controller/PacienteController.java
index 4ee8f15..8bf1836 100644
--- a/010_spring_boot/api_rest/api3/src/main/java/med/voll/api/controller/PacienteController.java
+++ b/010_spring_boot/api_rest/api3/src/main/java/med/voll/api/controller/PacienteController.java
@@ -1,5 +1,6 @@
package med.voll.api.controller;
+import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import jakarta.transaction.Transactional;
import jakarta.validation.Valid;
@@ -26,6 +27,7 @@ public class PacienteController {
private PacienteRepository pacienteRepository;
@PostMapping
+ @Operation(summary = "Registra un nuevo paciente")
public ResponseEntity registrarPaciente(
@RequestBody @Valid DatosRegistroPaciente datosRegistroPaciente,
UriComponentsBuilder uriComponentsBuilder) {
@@ -38,6 +40,7 @@ public class PacienteController {
}
@GetMapping
+ @Operation(summary = "Retorna listado de pacientes")
public ResponseEntity> listadoPacientes(
@PageableDefault(size = 5) Pageable paginacion) {
return ResponseEntity.ok(
@@ -47,6 +50,7 @@ public class PacienteController {
@PutMapping
@Transactional
+ @Operation(summary = "Actualiza información del paciente")
public ResponseEntity actualizarPaciente(
@RequestBody @Valid DatosActualizarPaciente datosActualizarPaciente) {
Paciente paciente = pacienteRepository.getReferenceById(datosActualizarPaciente.id());
@@ -60,6 +64,7 @@ public class PacienteController {
// Desactivar Paciente
@DeleteMapping("/{id}")
@Transactional
+ @Operation(summary = "Cambia el estado de un paciente a inactivo")
public ResponseEntity eliminarPaciente(@PathVariable Long id) {
Paciente paciente = pacienteRepository.getReferenceById(id);
paciente.desactivarPaciente();
@@ -67,6 +72,7 @@ public class PacienteController {
}
@GetMapping("/{id}")
+ @Operation(summary = "Retorna los detalles del paciente según ID")
public ResponseEntity retornaDatosPaciente(@PathVariable Long id) {
Paciente paciente = pacienteRepository.getReferenceById(id);
DatosRespuestaPaciente datosRespuestaPaciente = new DatosRespuestaPaciente(
diff --git a/010_spring_boot/api_rest/api3/src/main/resources/application-test.yml b/010_spring_boot/api_rest/api3/src/main/resources/application-test.yml
new file mode 100644
index 0000000..474c5c3
--- /dev/null
+++ b/010_spring_boot/api_rest/api3/src/main/resources/application-test.yml
@@ -0,0 +1,5 @@
+spring:
+ datasource:
+ url: jdbc:mysql://${TEST_DB_URL}?createDatabaseIfNotExist=true&serverTimezone=UTC
+ username: ${DB_USER}
+ password: ${DB_PASS}
\ No newline at end of file
diff --git a/010_spring_boot/api_rest/api3/src/test/java/med/voll/api/ApiApplicationTests.java b/010_spring_boot/api_rest/api3/src/test/java/med/voll/api/ApiApplicationTests.java
deleted file mode 100644
index eb360a5..0000000
--- a/010_spring_boot/api_rest/api3/src/test/java/med/voll/api/ApiApplicationTests.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package med.voll.api;
-
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.context.SpringBootTest;
-
-@SpringBootTest
-class ApiApplicationTests {
-
- @Test
- void contextLoads() {
- }
-
-}
diff --git a/010_spring_boot/api_rest/api3/src/test/java/med/voll/api/controller/ConsultaControllerTest.java b/010_spring_boot/api_rest/api3/src/test/java/med/voll/api/controller/ConsultaControllerTest.java
new file mode 100644
index 0000000..4f0fb35
--- /dev/null
+++ b/010_spring_boot/api_rest/api3/src/test/java/med/voll/api/controller/ConsultaControllerTest.java
@@ -0,0 +1,88 @@
+package med.voll.api.controller;
+
+import med.voll.api.domain.consulta.AgendaDeConsultaService;
+import med.voll.api.domain.consulta.DatosAgendarConsulta;
+import med.voll.api.domain.consulta.DatosDetalleConsulta;
+import med.voll.api.domain.medico.Especialidad;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.json.AutoConfigureJsonTesters;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.json.JacksonTester;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.web.servlet.MockMvc;
+
+import java.time.LocalDateTime;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+
+@SpringBootTest
+@AutoConfigureMockMvc
+@AutoConfigureJsonTesters
+@ActiveProfiles("test")
+class ConsultaControllerTest {
+
+ @Autowired
+ private MockMvc mvc;
+
+ @Autowired
+ private JacksonTester agendarConsultaJacksonTester;
+
+ @Autowired
+ private JacksonTester detalleConsultaJacksonTester;
+
+ @MockBean
+ private AgendaDeConsultaService agendaDeConsultaService;
+
+ @Test
+ @DisplayName("Debe retornar estado http 400 cuando datos ingresados no sean válidos")
+ @WithMockUser
+ void agendarEscenario1() throws Exception {
+ // given - when
+ var response = mvc.perform(post("/consultas")).andReturn().getResponse();
+ // then
+ assertEquals(HttpStatus.BAD_REQUEST.value(), response.getStatus());
+ }
+
+ @Test
+ @DisplayName("Debe retornar estado http 200 cuando datos ingresados sean válidos")
+ @WithMockUser
+ void agendarEscenario2() throws Exception {
+
+ //given
+ var fecha = LocalDateTime.now().plusHours(1);
+ var especialidad = Especialidad.CARDIOLOGIA;
+ var datos = new DatosDetalleConsulta(null,2l,5l,fecha);
+
+ // when
+ when(agendaDeConsultaService.agendar(any())).thenReturn(datos);
+
+ var response = mvc.perform(post("/consultas")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(agendarConsultaJacksonTester.write(
+ new DatosAgendarConsulta(
+ 2l,
+ 5l,
+ fecha,
+ especialidad))
+ .getJson()))
+ .andReturn().getResponse();
+
+ //then
+ assertEquals(HttpStatus.OK.value(), response.getStatus());
+
+ var jsonEsperado = detalleConsultaJacksonTester.write(datos).getJson();
+
+ assertEquals(response.getContentAsString(), jsonEsperado);
+ }
+
+}
\ No newline at end of file
diff --git a/010_spring_boot/api_rest/api3/src/test/java/med/voll/api/domain/medico/MedicoRepositoryTest.java b/010_spring_boot/api_rest/api3/src/test/java/med/voll/api/domain/medico/MedicoRepositoryTest.java
new file mode 100644
index 0000000..8bf493c
--- /dev/null
+++ b/010_spring_boot/api_rest/api3/src/test/java/med/voll/api/domain/medico/MedicoRepositoryTest.java
@@ -0,0 +1,115 @@
+package med.voll.api.domain.medico;
+
+import med.voll.api.domain.consulta.Consulta;
+import med.voll.api.domain.direccion.DatosDireccion;
+import med.voll.api.domain.paciente.DatosRegistroPaciente;
+import med.voll.api.domain.paciente.Paciente;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
+import org.springframework.test.context.ActiveProfiles;
+
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.temporal.TemporalAdjuster;
+import java.time.temporal.TemporalAdjusters;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@DataJpaTest
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+@ActiveProfiles("test")
+class MedicoRepositoryTest {
+
+ @Autowired
+ private MedicoRepository medicoRepository;
+ @Autowired
+ private TestEntityManager em;
+
+ @Test
+ @DisplayName("Debe retornar null cuando el médico tenga una consulta en ese horario")
+ void seleccionarMedicoConEspecialidadEnFechaEscenario1() {
+
+ var proximoLunes10H = LocalDate.now()
+ .with(TemporalAdjusters.next(DayOfWeek.MONDAY))
+ .atTime(10, 0);
+
+ var medico = registrarMedico("Jose","jose@mail.com", "123456", Especialidad.CARDIOLOGIA);
+ var paciente = registrarPaciente("antonio","antonio@mail.com","654321");
+ registrarConsulta(medico, paciente, proximoLunes10H);
+
+ var medicoLibre = medicoRepository.seleccionarMedicoConEspecialidadEnFecha(
+ Especialidad.CARDIOLOGIA,
+ proximoLunes10H) ;
+ assertNull(medicoLibre);
+ }
+
+ @Test
+ @DisplayName("Debe retornar el médico ingresado como disponible en ese horario")
+ void seleccionarMedicoConEspecialidadEnFechaEscenario2() {
+
+ var proximoLunes10H = LocalDate.now()
+ .with(TemporalAdjusters.next(DayOfWeek.MONDAY))
+ .atTime(10, 0);
+
+ var medico = registrarMedico("Jose","jose@mail.com", "123456", Especialidad.CARDIOLOGIA);
+
+ var medicoLibre = medicoRepository.seleccionarMedicoConEspecialidadEnFecha(
+ Especialidad.CARDIOLOGIA,
+ proximoLunes10H) ;
+
+ assertEquals(medicoLibre, medico);
+ }
+
+ private void registrarConsulta(Medico medico, Paciente paciente, LocalDateTime fecha) {
+ em.persist(new Consulta(null, medico, paciente, fecha, null));
+ }
+
+ private Medico registrarMedico(String nombre, String email, String documento, Especialidad especialidad) {
+ var medico = new Medico(datosMedico(nombre, email, documento, especialidad));
+ em.persist(medico);
+ return medico;
+ }
+
+ private Paciente registrarPaciente(String nombre, String email, String documento) {
+ var paciente = new Paciente(datosPaciente(nombre, email, documento));
+ em.persist(paciente);
+ return paciente;
+ }
+
+ private DatosRegistroMedico datosMedico(String nombre, String email, String documento, Especialidad especialidad) {
+ return new DatosRegistroMedico(
+ nombre,
+ email,
+ "61999999999",
+ documento,
+ especialidad,
+ datosDireccion()
+ );
+ }
+
+ private DatosRegistroPaciente datosPaciente(String nombre, String email, String documento) {
+ return new DatosRegistroPaciente(
+ nombre,
+ email,
+ "61999999999",
+ documento,
+ datosDireccion()
+ );
+ }
+
+ private DatosDireccion datosDireccion() {
+ return new DatosDireccion(
+ "loca",
+ "azul",
+ "Acapulco",
+ "321",
+ "12"
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/010_spring_boot/spring_boot_3.md b/010_spring_boot/spring_boot_3.md
index a6814f3..8d9cc41 100644
--- a/010_spring_boot/spring_boot_3.md
+++ b/010_spring_boot/spring_boot_3.md
@@ -969,3 +969,253 @@ por token.
---
+## Pruebas Automatizadas
+
+***¿Que se prueba?***
+
+- Cotroller -> API
+- Services -> Reglas de Negocio
+- Repository -> Queries
+
+#### Tipos de Tests
+
+- Test de caja negra
+- Test de caja blanca
+
+### Propiedades de los Tests
+
+[application-test.yml](./api_rest/api3/src/main/resources/application-test.yml)
+
+```yml
+spring:
+ datasource:
+ url: jdbc:mysql://${TEST_DB_URL}?createDatabaseIfNotExist=true&serverTimezone=UTC
+ username: ${DB_USER}
+ password: ${DB_PASS}
+```
+
+### Creación de Tests
+
+#### Test MedicoRepository
+
+Se crea el *Package*
+[`test.java.med.voll.api.domain.medico`](./api_rest/api3/src/test/java/med/voll/api/domain/medico/)
+y la clase
+[MedicoRepositoryTest](./api_rest/api3/src/test/java/med/voll/api/domain/medico/MedicoRepositoryTest.java)
+
+```java
+@DataJpaTest
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+@ActiveProfiles("test")
+class MedicoRepositoryTest {
+
+ @Autowired
+ private MedicoRepository medicoRepository;
+ @Autowired
+ private TestEntityManager em;
+
+ @Test
+ @DisplayName("Debe retornar null cuando el médico tenga una consulta en ese horario")
+ void seleccionarMedicoConEspecialidadEnFechaEscenario1() {
+
+ var proximoLunes10H = LocalDate.now()
+ .with(TemporalAdjusters.next(DayOfWeek.MONDAY))
+ .atTime(10, 0);
+
+ var medico = registrarMedico("Jose",
+ "jose@mail.com",
+ "123456",
+ Especialidad.CARDIOLOGIA);
+ var paciente = registrarPaciente("antonio","antonio@mail.com","654321");
+ registrarConsulta(medico, paciente, proximoLunes10H);
+
+ var medicoLibre = medicoRepository.seleccionarMedicoConEspecialidadEnFecha(
+ Especialidad.CARDIOLOGIA,
+ proximoLunes10H);
+ assertNull(medicoLibre);
+ }
+
+ @Test
+ @DisplayName("Debe retornar el médico ingresado como disponible en ese horario")
+ void seleccionarMedicoConEspecialidadEnFechaEscenario2() {
+
+ var proximoLunes10H = LocalDate.now()
+ .with(TemporalAdjusters.next(DayOfWeek.MONDAY))
+ .atTime(10, 0);
+
+ var medico = registrarMedico("Jose",
+ "jose@mail.com",
+ "123456",
+ Especialidad.CARDIOLOGIA);
+ var medicoLibre = medicoRepository.seleccionarMedicoConEspecialidadEnFecha(
+ Especialidad.CARDIOLOGIA,
+ proximoLunes10H) ;
+
+ assertEquals(medicoLibre, medico);
+ }
+
+ private void registrarConsulta(Medico medico,
+ Paciente paciente,
+ LocalDateTime fecha) {
+ em.persist(new Consulta(null, medico, paciente, fecha, null));
+ }
+
+ private Medico registrarMedico(String nombre,
+ String email,
+ String documento,
+ Especialidad especialidad) {
+ var medico = new Medico(datosMedico(nombre, email, documento, especialidad));
+ em.persist(medico);
+ return medico;
+ }
+
+ private Paciente registrarPaciente(String nombre,
+ String email,
+ String documento) {
+ var paciente = new Paciente(datosPaciente(nombre, email, documento));
+ em.persist(paciente);
+ return paciente;
+ }
+
+ private DatosRegistroMedico datosMedico(String nombre,
+ String email,
+ String documento,
+ Especialidad especialidad) {
+ return new DatosRegistroMedico(
+ nombre,
+ email,
+ "61999999999",
+ documento,
+ especialidad,
+ datosDireccion()
+ );
+ }
+
+ private DatosRegistroPaciente datosPaciente(String nombre,
+ String email,
+ String documento) {
+ return new DatosRegistroPaciente(
+ nombre,
+ email,
+ "61999999999",
+ documento,
+ datosDireccion()
+ );
+ }
+
+ private DatosDireccion datosDireccion() {
+ return new DatosDireccion(
+ "Loca",
+ "Azul",
+ "Acapulco",
+ "321",
+ "12"
+ );
+ }
+
+}
+```
+
+### Test ConsultaController
+
+Clase
+[ConsultaControllerTest](./api_rest/api3/src/test/java/med/voll/api/controller/ConsultaControllerTest.java)
+en *package*
+[`test.java.med.voll.api.controler`](./api_rest/api3/src/test/java/med/voll/api/controller/)
+
+```java
+package med.voll.api.controller;
+
+import med.voll.api.domain.consulta.AgendaDeConsultaService;
+import med.voll.api.domain.consulta.DatosAgendarConsulta;
+import med.voll.api.domain.consulta.DatosDetalleConsulta;
+import med.voll.api.domain.medico.Especialidad;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.json.AutoConfigureJsonTesters;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.json.JacksonTester;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.web.servlet.MockMvc;
+
+import java.time.LocalDateTime;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+
+@SpringBootTest
+@AutoConfigureMockMvc
+@AutoConfigureJsonTesters
+@ActiveProfiles("test")
+class ConsultaControllerTest {
+
+ @Autowired
+ private MockMvc mvc;
+
+ @Autowired
+ private JacksonTester agendarConsultaJacksonTester;
+
+ @Autowired
+ private JacksonTester detalleConsultaJacksonTester;
+
+ @MockBean
+ private AgendaDeConsultaService agendaDeConsultaService;
+
+ @Test
+ @DisplayName("Debe retornar estado http 400 cuando datos ingresados no sean válidos")
+ @WithMockUser
+ void agendarEscenario1() throws Exception {
+ // given - when
+ var response = mvc.perform(post("/consultas")).andReturn().getResponse();
+ // then
+ assertEquals(HttpStatus.BAD_REQUEST.value(), response.getStatus());
+ }
+
+ @Test
+ @DisplayName("Debe retornar estado http 200 cuando datos ingresados sean válidos")
+ @WithMockUser
+ void agendarEscenario2() throws Exception {
+
+ //given
+ var fecha = LocalDateTime.now().plusHours(1);
+ var especialidad = Especialidad.CARDIOLOGIA;
+ var datos = new DatosDetalleConsulta(null,2l,5l,fecha);
+
+ // when
+ when(agendaDeConsultaService.agendar(any())).thenReturn(datos);
+
+ var response = mvc.perform(post("/consultas")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(agendarConsultaJacksonTester.write(
+ new DatosAgendarConsulta(
+ 2l,
+ 5l,
+ fecha,
+ especialidad))
+ .getJson()))
+ .andReturn().getResponse();
+
+ //then
+ assertEquals(HttpStatus.OK.value(), response.getStatus());
+
+ var jsonEsperado = detalleConsultaJacksonTester.write(datos).getJson();
+
+ assertEquals(response.getContentAsString(), jsonEsperado);
+ }
+
+}
+```
+
+---
+
+## Build del proyecto
+
+