Ticker

6/recent/ticker-posts

CRUD con Spring Boot, PostgreSQL y manipulación de datos aplicando @Test JUnit



En este tutorial desarollaremos los métodos con relación a una aplicación CRUD haciendo uso de nuestra base de datos PostgreSQL y Spring Boot, finalmente, aplicaremos Test JUnit para manipular los datos.

Requisitos:

  • PostgreSQL 14.
  • pgAmin
  • Java 17.
  • Dependencias Maven 3.8.6.
  • Spring Initializr.
  • Spring Boot 3.0.1.
  • IntelliJ IDEA Ultimate.

Lo que veremos en este tutorial:

  1. Consideraciones.
  2. ¿Qué es CRUD y Unit Test?
  3. Crear los métodos CRUD.
  4. Manipular datos con @Test JUnit.
  5. Conclusiones.

1. Consideraciones:

Las consideraciones principales para este tutorial son:

  1. Cumplir con los requisitos detallados al inicio de este tutorial
  2. Crear el proyecto con Spring Initializr de nombre crud-test-unit-spring-boot, te sugiero revisar el siguiente tutorial: Creando proyectos con Spring Initializr
  3. Tener la base de datos creada, te sugiero revisar el siguiente tutorial: Creando una base de datos con pgAdmin Management Tools for PostgreSQL.
  4. Tener la conexión a la base de datos ya implementado y los paquete con relación a la entidad (entity), repositorio (repository) y negocio (business), sugiero revisar el siguiente tutorial: Conexión e inserción de datos con PostgreSQL y Spring Boot.

2. ¿Qué es CRUD y Unit Test?


2.1. ¿Qué es CRUD?

CRUD: Simplemente es el acrónimo en ingles de Create, Read, Update y Delete, es decir, son las operaciones básica que se realiza con relación a las operaciones de crear, leer, actualizar y borrar registro en una base de datos relacional o no relacional; con mayor detalle se describe cada acrónimo como:

Create (Crear): Acción para la creación o inserción de nuevos registros en nuestra tablas de una determinada base de datos.

Read (Leer): Acción de consultar registros específicos según el filtro aplicado a una o varias tablas de nuestra base de datos.

Update (Actualizar): Acción para actualizar la información de un registro o varios registros de una determinada o varias tablas.

Delete (Borrar): Acción de borrar un registro según el críterio de los filtros que se aplica a la sentencia SQL.

2.1. ¿Qué es Unit Test?

Un Unit Test o prueba unitaria, se define como la prueba que nos va a permitir verificar una unidad o parte de nuestro código, es decir, nos permite probar y verificar partes aisladas de nuestro código para asegurar que la funcionalidad que hemos desarrollado funciona correctamente.

Partes aisladas de nuestro código, hace referencia a extracto o métodos de código a probar y verificar el correcto funcionamiento de nuestra aplicación.


3. Crear los métodos CRUD:


Estructura básica de nuestro proyecto crud-test-unit-spring-boot


Recordemos que la configuración de conexión a la base de datos ya se tiene que tener implementado, y la creación de los paquete con relación a la entidad (entity), repositorio (repository) y negocio (business).

3.1. Para el desarrollo de los métodos con relación al CRUD, se crea la ENTIDAD de nombre Client - dicha entidad será invocado en las clases de tipo interfaz de repositorio y negocio. La clase (entidad) se crea en el paquete entidad (entity):

package com.hadsonpar.crudtestunitspringboot.entity;

import jakarta.persistence.*;

@Entity
//Estos nos servirá crear la tabla en la base de
// datos con el nombre de tbclient
@Table(name = "tbclient")
public class Client {
// Atributos de nuestra entidad client
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long code;
private String name;
private String address;

public Client(){

}

public Long getCode() {
return code;
}

public void setCode(Long code) {
this.code = code;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}
}

3.2. Seguidamente, se crea la clase INTERFAZ REPOSITORIO de nombre IClientRepository. La clase de tipo interfaz se crea en el paquete repositorio (repository):

package com.hadsonpar.crudtestunitspringboot.repository;
import com.hadsonpar.crudtestunitspringboot.entity.Client;
import org.springframework.data.jpa.repository.JpaRepository;

public interface IClientRepository extends JpaRepository<Client, Long> {
}


Recordemos que la INTERFAZ REPOSITORIO extiende al JpaRepository y asocia a la entidad Client. El JpaRepository contiene las API para las operaciones CRUD básicas, las API para la paginación y las API para la clasificación.


3.3. CREAR LOS MÉTODOS Create (Crear): 

3.3.1. En primer instancia debemos crear la clase INTERFAZ NEGOCIO de nombre IClientBusiness. Seguidamente, crear el método de Create (Crear) registros - nombre insertClient. La clase de tipo interfaz se crea en el paquete negocio (business):

package com.hadsonpar.crudtestunitspringboot.business;

import com.hadsonpar.crudtestunitspringboot.entity.Client;

import java.util.List;

public interface IClientBusiness {
public Client insertClient(Client client);
}

3.3.2. En segunda instancia debemos crear la clase NEGOCIO de nombre ClientBusiness e implementar (implements IClientBusiness) a la INTERFAZ IClientBusiness. Seguidamente crear el método de Create (Crear) registros que invoca al save de JpaRepository. La clase se crea en el paquete negocio (business):

package com.hadsonpar.crudtestunitspringboot.business;

import com.hadsonpar.crudtestunitspringboot.entity.Client;
import com.hadsonpar.crudtestunitspringboot.repository.IClientRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ClientBusiness implements IClientBusiness {

@Autowired
IClientRepository iClientRepository;

@Override
public Client insertClient(Client client) {
return iClientRepository.save(client);
}
}

Importa la clase INTERFAZ NEGOCIO IClientRepository conjuntamente con la anotación @Autowired.

3.4. CREAR LOS MÉTODOS Read (Leer):

3.4.1. En la clase INTERFAZ NEGOCIO de nombre IClientBusiness, crear el método de Read (Leerregistros - nombre listClient:

package com.hadsonpar.crudtestunitspringboot.business;

import com.hadsonpar.crudtestunitspringboot.entity.Client;

import java.util.List;

public interface IClientBusiness {
public Client insertClient(Client client);
public List<Client> listClient();
}

3.4.2. En la clase NEGOCIO de nombre ClientBusiness, crear el método de Read (Leerregistros que invoca al save de JpaRepository:

package com.hadsonpar.crudtestunitspringboot.business;

import com.hadsonpar.crudtestunitspringboot.entity.Client;
import com.hadsonpar.crudtestunitspringboot.repository.IClientRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ClientBusiness implements IClientBusiness {

@Autowired
IClientRepository iClientRepository;

@Override
public Client insertClient(Client client) {
return iClientRepository.save(client);
}

@Override
public List<Client> listClient() {
return iClientRepository.findAll();
}
}

3.5. CREAR LOS MÉTODOS Update (Actualizar)

3.5.1. Para la actualización de los registros se implementará el método buscar con la finalidad de aplicar una búsqueda por código y realizar la actualización. En la clase INTERFAZ NEGOCIO de nombre IClientBusiness, crear el método de nombre findClient:

package com.hadsonpar.crudtestunitspringboot.business;

import com.hadsonpar.crudtestunitspringboot.entity.Client;

import java.util.List;

public interface IClientBusiness {
public Client findClient(Long pcode) throws Exception;
}

3.5.2. En la clase NEGOCIO de nombre ClientBusiness, crear el método de nombre findClient que invoca al findById de JpaRepository para filtrar la busqueda por id de la entidad:

package com.hadsonpar.crudtestunitspringboot.business;

import com.hadsonpar.crudtestunitspringboot.entity.Client;
import com.hadsonpar.crudtestunitspringboot.repository.IClientRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ClientBusiness implements IClientBusiness {

@Autowired
IClientRepository iClientRepository;


@Override
public Client findClient(Long pcode) throws Exception {
return iClientRepository.findById(pcode).orElseThrow(
() -> new Exception("No se encontró la entidad"));
}
}

3.5.3. En la clase INTERFAZ NEGOCIO de nombre IClientBusiness, crear el método de Update (Actualizarregistros - nombre updateClient:

package com.hadsonpar.crudtestunitspringboot.business;

import com.hadsonpar.crudtestunitspringboot.entity.Client;

import java.util.List;

public interface IClientBusiness {
public Client insertClient(Client client);
public Client findClient(Long pcode) throws Exception;
public List<Client> listClient();
public Client updateClient(Client client) throws Exception;
}

3.5.4. En la clase NEGOCIO de nombre ClientBusiness, crear el método de Update (Actualizarregistros que invoca al save de JpaRepository:

package com.hadsonpar.crudtestunitspringboot.business;

import com.hadsonpar.crudtestunitspringboot.entity.Client;
import com.hadsonpar.crudtestunitspringboot.repository.IClientRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ClientBusiness implements IClientBusiness {

@Autowired
IClientRepository iClientRepository;

@Override
public Client findClient(Long pcode) throws Exception {
return iClientRepository.findById(pcode).orElseThrow(
() -> new Exception("No se encontró la entidad"));
}

@Override
public Client updateClient(Client client) throws Exception{
findClient(client.getCode());//Invocar al metodo buscar por código
return iClientRepository.save(client);
}
}

3.6. CREAR LOS MÉTODOS Delete (Borrar)

3.6.1. En la clase INTERFAZ NEGOCIO de nombre IClientBusiness, crear el método de Delete (Borrarregistros de nombre deleteClient(Long id):

package com.hadsonpar.crudtestunitspringboot.business;

import com.hadsonpar.crudtestunitspringboot.entity.Client;

import java.util.List;

public interface IClientBusiness {
public Client insertClient(Client client);
public Client findClient(Long pcode) throws Exception;
public List<Client> listClient();
public Client updateClient(Client client) throws Exception;
public void deleteClient(Long id) throws Exception;
}

3.6.2. En la clase NEGOCIO de nombre ClientBusiness, crear el método de Delete (Borrar) que invoca al método deleteById(id) de JpaRepository:

package com.hadsonpar.crudtestunitspringboot.business;

import com.hadsonpar.crudtestunitspringboot.entity.Client;
import com.hadsonpar.crudtestunitspringboot.repository.IClientRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ClientBusiness implements IClientBusiness {

@Autowired
IClientRepository iClientRepository;

@Override
public Client insertClient(Client client) {
return iClientRepository.save(client);
}

@Override
public Client findClient(Long pcode) throws Exception {
return iClientRepository.findById(pcode).orElseThrow(
() -> new Exception("No se encontró la entidad"));
}

@Override
public List<Client> listClient() {
return iClientRepository.findAll();
}

@Override
public Client updateClient(Client client) throws Exception{
findClient(client.getCode());//Invocar al metodo buscar por código
return iClientRepository.save(client);
}

@Override
public void deleteClient(Long id) throws Exception{
iClientRepository.deleteById(id);
}
}


4. Manipular datos con @Test JUnit:

Se debe crear los método de tupo test junit en la clase CrudTestUnitSpringBootApplicationTests de nuestro proyecto crud-test-unit-spring-boot:

Clase creada automáticamente al crear el proyecto

package com.hadsonpar.crudtestunitspringboot;

import com.hadsonpar.crudtestunitspringboot.business.IClientBusiness;
import com.hadsonpar.crudtestunitspringboot.entity.Client;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class CrudTestUnitSpringBootApplicationTests {

@Autowired
private IClientBusiness clientBusiness;
@Test
void contextLoads() {
}

@Test//Create
void testInsertClient(){
Client client = new Client();

client.setName("Carmen Guerra");
client.setAddress("Jr Carlindo");

clientBusiness.insertClient(client);
}

@Test//Read
void testSelectClient(){
List<Client> list;
list = clientBusiness.listClient();

for(Client p:list){
System.out.println(p.getName() + " - " + p.getAddress());
}
}

@Test//Update
void testUpdateClient(){
try {
Client client = new Client();
client.setCode(1L);
client.setName("Cesar Paredes");
client.setAddress("Los Campos");

clientBusiness.updateClient(client);
}catch (Exception e){
System.out.println(e.getMessage());
}
}

@Test//Test JUnit Delete
void testDeleteClient() throws Exception{
//registro a eliminar según código 5
long clientId = 5L;
clientBusiness.deleteClient(clientId);
}
}

En un próximo tutorial profundizaré el tema de pruebas unitarias y pruebas de integración aplicado a nuestro proyecto CRUD con Spring Boot y PostgreSQL.


5. Conclusiones:

  • Revisamos conceptos básicos con relación al significado CRUD y Test JUnit 
  • Desarrollamos una aplicación CRUD haciendo uso de la persistencia de datos en base a interfaz genéricas de un repositorio JpaRepository.
  • Implementamos los métodos de tipos Test JUnit.

Referencias:

Código disponible en GitHub

Gracias nuevamente 😊; comentarios y apreciaciones son bienvenido, un fuerte abrazo para todos ✌...!!! 

Publicar un comentario

0 Comentarios