- Enviar parámetros en el cuerpo de una petición POST.
- Crear una prueba unitaria que valide el funcionamiento de los controladores.
- Simular el comportamiento de los objetos en la capa de servicios de la aplicación (lógica de negocio) usando objetos mock.
- Tener instalado el IDE IntelliJ Idea Community Edition con el plugin de Lombok activado.
- Tener instalada la última versión del JDK 11 o 17.
-
Crea un nuevo proyecto usando Spring Initilizr y agrega las dependencias de Spring Web y Lombok.
-
Crea los subpaquetes:
controllers
,model
, yservices
. -
Crea una clase
Cliente
, con las anotaciones@Data
y@Builder
, y los siguientes atributos:- private Long id;
- private String nombre;
- private String correoContacto;
- private int numeroEmpleados;
- private String direccion;
-
Crea una interface
ClienteService
con los siguientes métodos:- Cliente guardaCliente(Cliente cliente);
- Optional obtenCliente(Long clienteId);
-
Crea un servicio
ClienteController
e implementa los siguientes métodos:
@PostMapping
public ResponseEntity<Void> creaCliente(@RequestBody Cliente cliente) {
}
@GetMapping("/{clienteId}")
public ResponseEntity<Cliente> getCliente(@PathVariable Long clienteId) {
}
- Crea una clase de prueba
ClienteControllerTest
que verifique cada una de las operaciones. - Para verificar el método POST debes usar el método
post
de la claseMockMvcRequestBuilders
y generar un objeto Json conObjectMapper
Solución
-
Crea un proyecto Maven usando Spring Initializr desde el IDE IntelliJ Idea.
-
En la ventana que se abre selecciona las siguientes opciones:
- Grupo, artefacto y nombre del proyecto.
- Tipo de proyecto: Maven Project.
- Lenguaje: Java.
- Forma de empaquetar la aplicación: jar.
- Versión de Java: 11.
-
En la siguiente ventana elige Spring Web y Lombok como dependencias del proyecto. En automático se agregarán también las dependencias para realizar pruebas unitarias.
-
Dale un nombre y una ubicación al proyecto y presiona el botón Finish.
-
En el proyecto que se acaba de crear debes tener el siguiente paquete
org.bedu.java.backend.sesion7.reto2
. Dentro crea los subpaquetes:controllers
,model
, yservices
. -
Dentro del paquete
model
crea una claseCliente
con los siguientes atributos, y las anotaciones@Data
y@Builder
:
@Data
@Builder
public class Cliente {
private Long id;
private String nombre;
private String correoContacto;
private int numeroEmpleados;
private String direccion;
}
- En el paquete
services
crea una interface llamadaClienteService
. Como no nos interesa implementar esta interface en este momento, la simularemos para realizar las pruebas unitarias.
public class ClienteService {
}
- Coloca dos métodos dentro de esta clase, uno para guardar a un
Cliente
y otro para recuperarlo por su id:
public interface ClienteService {
Cliente guardaCliente(Cliente cliente);
Optional<Cliente> obtenCliente(Long clienteId);
}
- En el paquete
controllers
agrega una claseClienteController
y decórala con@RestController
. Esta clase será el punto de entrada de las peticiones y delegará sus funcionalidades aClienteService
:
@RestController
@RequestMapping("/cliente")
@RequiredArgsConstructor
public class ClienteController {
private final ClienteService clienteService;
@PostMapping
public ResponseEntity<Void> creaCliente(@RequestBody Cliente cliente) {
Cliente clienteNuevo = clienteService.guardaCliente(cliente);
return ResponseEntity.created(URI.create(String.valueOf(clienteNuevo.getId()))).build();
}
@GetMapping("/{clienteId}")
public ResponseEntity<Cliente> getCliente(@PathVariable Long clienteId) {
Optional<Cliente> clienteDb = clienteService.obtenCliente(clienteId);
if (clienteDb.isEmpty()) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "El cliente especificado no existe.");
}
return ResponseEntity.ok(clienteDb.get());
}
}
-
En el directorio de pruebas de Maven agrega una nueva clase llamada
ClienteControllerTest
. -
Decora la nueva clase con la anotación
@WebMvcTest(ClienteController.class)
@WebMvcTest(ClienteController.class)
class ClienteControllerTest {
}
- Agrega una instancia de tipo
MockMvc
y decórala con la anotación@Autowired
:
@Autowired
private MockMvc mockMvc;
- Agrega una instancia de tipo
ClienteService
y decórala con la anotación@MockBean
:
@MockBean
private ClienteService clienteService;
- Crea un método llamado
obtenClienteTest
y decóralo con la anotación@Test
:
@Test
public void obtenClienteTest() throws Exception {
}
- Dentro de este método indica el comportamiento que tendrá el objeto mock
clienteService
al invocar a su métodoobtenCliente
. En este caso debe regresar un objeto de tipoOptional<Cliente>
:
given(clienteService.obtenCliente(anyLong())).willReturn(Optional.of(Cliente.builder().id(1L).nombre("Nombre").correoContacto("cliente@contacto.com").build()));
- Por último, usa el método
perform
de la instancia demockMvc
para simular una petición GET. Valida que los resutados regrsados son igual a los esperados.
mockMvc.perform(get("/cliente/1")
.content(MediaType.APPLICATION_JSON_VALUE))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.id", is(1)))
.andExpect(jsonPath("$.correoContacto", is("cliente@contacto.com")))
.andExpect(jsonPath("$.nombre", is("Nombre")));
El método completo queda de la siguiente forma:
@Test
void obtenClienteTest() throws Exception {
given(clienteService.obtenCliente(anyLong())).willReturn(Optional.of(Cliente.builder().id(1L).nombre("Nombre").correoContacto("cliente@contacto.com").build()));
mockMvc.perform(get("/cliente/1")
.content(MediaType.APPLICATION_JSON_VALUE))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.id", is(1)))
.andExpect(jsonPath("$.correoContacto", is("cliente@contacto.com")))
.andExpect(jsonPath("$.nombre", is("Nombre")));
}
17.Crea un método llamado creaClienteTest
y decóralo con la anotación @Test
:
@Test
public void creaClienteTest() throws Exception {
}
- Dentro de este método indica el comportamiento que tendrá el objeto mock
clienteService
al invocar a su métodoguardaCliente
. En este caso debe regresar un objeto de tipoCliente
:
Cliente clienteParametro = Cliente.builder().nombre("Nombre").direccion("Direccion").numeroEmpleados(10).correoContacto("contacto@cliente.com").build();
Cliente clienteRespuesta = Cliente.builder().id(1L).nombre("Nombre").direccion("Direccion").numeroEmpleados(10).correoContacto("contacto@cliente.com").build();
given(clienteService.guardaCliente(clienteParametro)).willReturn(clienteRespuesta);
- Por último, usa el método
perform
de la instancia demockMvc
para simular una petición GET. Valida que los resutados regrsados son igual a los esperados.
mockMvc.perform(post("/cliente")
.contentType(MediaType.APPLICATION_JSON)
.content(new ObjectMapper().writeValueAsString(clienteParametro)))
.andExpect(status().isCreated());
El método completo queda de la siguiente forma:
@Test
void creaClienteTest() throws Exception {
Cliente clienteParametro = Cliente.builder().nombre("Nombre").direccion("Direccion").numeroEmpleados(10).correoContacto("contacto@cliente.com").build();
Cliente clienteRespuesta = Cliente.builder().id(1L).nombre("Nombre").direccion("Direccion").numeroEmpleados(10).correoContacto("contacto@cliente.com").build();
given(clienteService.guardaCliente(clienteParametro)).willReturn(clienteRespuesta);
mockMvc.perform(post("/cliente")
.contentType(MediaType.APPLICATION_JSON)
.content(new ObjectMapper().writeValueAsString(clienteParametro)))
.andExpect(status().isCreated());
}
- Ejecuta la prueba. Debes ver el siguiente resultado en la consola de IntelliJ: