Commit c0779679 by Antonio Rueda

Implementación de repositorios y tests de integración con persistencia

parent e5609ca6
......@@ -38,8 +38,7 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
......@@ -50,19 +49,7 @@
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<!--
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>jakarta.el</artifactId>
<version>3.0.3</version>
</dependency>
-->
</dependency>
</dependencies>
<build>
......
......@@ -14,7 +14,7 @@ import org.springframework.context.ApplicationContext;
*
* @author admin
*/
@SpringBootApplication(scanBasePackages="es.ujaen.dae.ujacoin.servicios")
@SpringBootApplication(scanBasePackages={"es.ujaen.dae.ujacoin.servicios", "es.ujaen.dae.ujacoin.repositorios"})
@EntityScan(basePackages="es.ujaen.dae.ujacoin.entidades")
public class UjaCoinApp {
public static void main(String[] args) throws Exception {
......
......@@ -13,6 +13,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
......@@ -58,7 +59,7 @@ public class Cliente implements Serializable {
/** Tarjetas asociadas al cliente (no tiene por qué ser el titular */
@OneToMany(fetch = FetchType.EAGER)
@OneToMany(fetch = FetchType.EAGER, cascade=CascadeType.ALL)
@JoinColumn(name="cliente_dni")
List<Tarjeta> tarjetas;
......
......@@ -13,6 +13,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
......@@ -45,10 +46,13 @@ public class Cuenta {
Cliente titular;
/** Lista de movimientos */
@OneToMany
@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="cuenta_num")
List<Movimiento> movimientos;
public Cuenta() {
}
public Cuenta(String num, Cliente titular) {
this.num = num;
this.titular = titular;
......@@ -91,17 +95,21 @@ public class Cuenta {
* @return la lista de movimientos dentro del intervalo de fechas indicado
*/
public List<Movimiento> listarMovimientosDesdeHasta(LocalDateTime fechaHoraDesde, LocalDateTime fechaHoraHasta) {
LocalDateTime fechaHoraDesdeConsulta = Optional.ofNullable(fechaHoraHasta).orElseGet(
() -> {
LocalDateTime ahora = LocalDateTime.now();
return ahora.minusDays(ahora.getDayOfMonth() - 1);
}
);
LocalDateTime fechaHoraHastaConsulta = Optional.ofNullable(fechaHoraHasta).orElse(LocalDateTime.now());
if (fechaHoraDesde == null) {
LocalDateTime ahora = LocalDateTime.now();
fechaHoraDesde = ahora.minusDays(ahora.getDayOfMonth() - 1);
}
if (fechaHoraHasta == null) {
fechaHoraHasta = LocalDateTime.now();
}
final LocalDateTime desde = fechaHoraDesde;
final LocalDateTime hasta = fechaHoraHasta;
return movimientos.stream().filter(m ->
m.getFechaHora().isAfter(fechaHoraDesdeConsulta) &&
m.getFechaHora().isBefore(fechaHoraHastaConsulta)
m.getFechaHora().isAfter(desde) &&
m.getFechaHora().isBefore(hasta)
).collect(Collectors.toList());
}
......
......@@ -31,7 +31,6 @@ public abstract class Movimiento implements Serializable {
@PastOrPresent
LocalDateTime fechaHora;
/** Importe del movimiento. Los valores negativos representan retiradas de dinero */
@Positive
float importe;
public Movimiento() {
......
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package es.ujaen.dae.ujacoin.repositorios;
import es.ujaen.dae.ujacoin.entidades.Cliente;
import es.ujaen.dae.ujacoin.entidades.Tarjeta;
import java.util.Optional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
/**
*
* @author ajrueda
*/
@Repository
@Transactional
public class RepositorioClientes {
@PersistenceContext
EntityManager em;
public Optional<Cliente> buscar(String dni) {
return Optional.ofNullable(em.find(Cliente.class, dni));
}
public void guardar(Cliente cliente) {
em.persist(cliente);
}
public void nuevaTarjeta(Cliente cliente, Tarjeta tarjeta) {
em.persist(tarjeta);
cliente = em.merge(cliente);
cliente.nuevaTarjeta(tarjeta);
}
public void actualizar(Cliente cliente) {
em.merge(cliente);
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package es.ujaen.dae.ujacoin.repositorios;
import es.ujaen.dae.ujacoin.entidades.Cuenta;
import java.util.Optional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
/**
*
* @author ajrueda
*/
@Repository
@Transactional
public class RepositorioCuentas {
@PersistenceContext
EntityManager em;
public Optional<Cuenta> buscar(String num) {
return Optional.ofNullable(em.find(Cuenta.class, num));
}
public void guardar(Cuenta cuenta) {
em.persist(cuenta);
}
}
......@@ -4,7 +4,7 @@ spring.datasource.url: jdbc:mysql://localhost:33060/ujacoin
spring.datasource.username: ujacoin
spring.datasource.password: secret
spring.jpa.properties.javax.persistence.schema-generation.database.action: drop-and-create
spring.jpa.properties.javax.persistence.schema-generation.database.action: none
spring.data.jpa.repositories.bootstrap-mode: default
......
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package es.ujaen.dae.ujacoin.servicios;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
/**
* Servicio auxiliar de borrado de los datos en la base de datos (sólo para testing)
* @author ajrueda
*/
@Service
public class ServicioLimpiadoBaseDatos {
@PersistenceContext
EntityManager em;
@Autowired
TransactionTemplate transactionTemplate;
/**
* Lista de entidades a borrar. Ojo: el orden es muy importante
* para evitar errores de violación de integridad
*/
final String[] entidades = {
"Movimiento",
"Cuenta",
"Tarjeta",
"Cliente"
};
final String deleteFrom = "delete from ";
/** Realizar borrado */
void limpiar() {
transactionTemplate.executeWithoutResult(transactionStatus -> {
for (String tabla : entidades) {
em.createQuery(deleteFrom + tabla).executeUpdate();
}
});
}
}
......@@ -9,37 +9,40 @@ import es.ujaen.dae.ujacoin.entidades.Cliente;
import es.ujaen.dae.ujacoin.entidades.Cuenta;
import es.ujaen.dae.ujacoin.entidades.Tarjeta;
import es.ujaen.dae.ujacoin.entidades.movimientos.Ingreso;
import es.ujaen.dae.ujacoin.entidades.movimientos.Movimiento;
import es.ujaen.dae.ujacoin.entidades.movimientos.TransferenciaEmitida;
import es.ujaen.dae.ujacoin.entidades.movimientos.TransferenciaRecibida;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import javax.validation.ConstraintViolationException;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.MethodMode;
/**
*
* @author ajrueda
*/
//@Disabled
// @Disabled
@SpringBootTest(classes = es.ujaen.dae.ujacoin.app.UjaCoinApp.class)
public class ServicioUjaCoinTest {
@Autowired
ServicioUjaCoin servicioUjaCoin;
@Autowired
ServicioLimpiadoBaseDatos limpiadorBaseDatos;
@Test
public void testAccesoServicioUjaCoin() {
Assertions.assertThat(servicioUjaCoin).isNotNull();
}
@Test
@DirtiesContext(methodMode = MethodMode.AFTER_METHOD)
public void testAltaClienteInvalido() {
// Cliente con e-mail incorrecto!!!
Cliente cliente = new Cliente(
......@@ -57,7 +60,6 @@ public class ServicioUjaCoinTest {
}
@Test
@DirtiesContext(methodMode = MethodMode.AFTER_METHOD)
public void testAltaYLoginClienteCuenta() {
Cliente cliente = new Cliente(
"11995667D",
......@@ -68,15 +70,60 @@ public class ServicioUjaCoinTest {
"jee@gmail.com",
"clave");
Cuenta cuenta = servicioUjaCoin.altaCliente(cliente);
servicioUjaCoin.altaCliente(cliente);
Optional<Cliente> clienteLogin = servicioUjaCoin.loginCliente(cliente.getDni(), "clave");
Assertions.assertThat(clienteLogin.isPresent()).isTrue();
Assertions.assertThat(clienteLogin.get()).isEqualTo(cliente);
Assertions.assertThat(clienteLogin.get().getDni()).isEqualTo(cliente.getDni());
Assertions.assertThat(clienteLogin.get().verCuentas()).isNotEmpty();
}
@Test
public void testCreacionCuentaAdicional() {
Cliente cliente = new Cliente(
"11995667D",
"Juan España España",
LocalDate.of(1990, 11, 1),
"Cl La Luz, 13 - Jaén",
"988674533",
"jee@gmail.com",
"clave");
servicioUjaCoin.altaCliente(cliente);
// Crear cuenta adicional
servicioUjaCoin.crearCuenta(cliente.getDni());
Optional<Cliente> clienteLogin = servicioUjaCoin.loginCliente(cliente.getDni(), "clave");
Assertions.assertThat(clienteLogin.get().verCuentas()).hasSize(2);
Assertions.assertThat(clienteLogin.get().verCuentas().get(0).getNum())
.isNotEqualTo(clienteLogin.get().verCuentas().get(1).getNum());
}
@Test
@DirtiesContext(methodMode = MethodMode.AFTER_METHOD)
public void testAnadirTarjetaACliente() {
// Registrar cliente y realizar login
Cliente cliente = new Cliente(
"11995667D",
"Juan España España",
LocalDate.of(1990, 11, 1),
"Cl La Luz, 13 - Jaén",
"988674533",
"jee@gmail.com",
"clave");
// Crear cliente
servicioUjaCoin.altaCliente(cliente);
// Añadir una tarjeta
Tarjeta tarjeta = new Tarjeta("4111111111111111", cliente.getNombre(), LocalDate.of(2022, 12, 1), "365");
servicioUjaCoin.registrarTarjeta(cliente.getDni(), tarjeta);
Cliente clienteLogin = servicioUjaCoin.loginCliente(cliente.getDni(), "clave").get();
Assertions.assertThat(clienteLogin.verTarjeta(tarjeta.getNum())).isNotEmpty();
}
@Test
public void testIngreso() {
// Registrar cliente y realizar login
Cliente cliente = new Cliente(
......@@ -102,13 +149,14 @@ public class ServicioUjaCoinTest {
// Realizar ingreso y comprobar estado de la cuenta
servicioUjaCoin.ingreso(cuentas.get(0).getNum(), tarjeta.getNum(), 1000);
Assertions.assertThat(cuentas.get(0).listarMovimientos()).hasSize(1);
Assertions.assertThat(cuentas.get(0).listarMovimientos().get(0)).isInstanceOf(Ingreso.class);
Assertions.assertThat(cuentas.get(0).getSaldo()).isEqualTo(1000);
List<Movimiento> movimientos = servicioUjaCoin.listarMovimientosDesde(cuentas.get(0).getNum(), LocalDateTime.MIN);
Assertions.assertThat(movimientos).hasSize(1);
Assertions.assertThat(movimientos.get(0)).isInstanceOf(Ingreso.class);
Assertions.assertThat(movimientos.get(0).getImporte()).isEqualTo(1000);
}
@Test
@DirtiesContext(methodMode = MethodMode.AFTER_METHOD)
@Test
public void testTransferencia() {
// Registrar cliente
Cliente cliente = new Cliente(
......@@ -120,7 +168,7 @@ public class ServicioUjaCoinTest {
"jee@gmail.com",
"claveyyy");
Cuenta cuenta = servicioUjaCoin.altaCliente(cliente);
Cuenta cuentaOrigen = servicioUjaCoin.altaCliente(cliente);
// Añadir una tarjeta
Tarjeta tarjeta = new Tarjeta("4111111111111111", cliente.getNombre(), LocalDate.of(2022, 12, 1), "365");
......@@ -128,7 +176,6 @@ public class ServicioUjaCoinTest {
cliente.nuevaTarjeta(tarjeta);
// Obtener cuenta y realizar ingreso en cuenta
Cuenta cuentaOrigen = servicioUjaCoin.verCuentas(cliente.getDni()).get(0);
servicioUjaCoin.ingreso(cuentaOrigen.getNum(), tarjeta.getNum(), 1000);
// Crear segundo cliente
......@@ -146,12 +193,26 @@ public class ServicioUjaCoinTest {
// Realizar transferencia y comprobar movimientos
servicioUjaCoin.transferencia(cuentaOrigen.getNum(), cuentaDestino.getNum(), 500);
Assertions.assertThat(cuentaOrigen.listarMovimientos()).hasSize(2);
Assertions.assertThat(cuentaOrigen.listarMovimientos().get(1)).isInstanceOf(TransferenciaEmitida.class);
// Refrescar cuenta origen y destino
cuentaOrigen = servicioUjaCoin.verCuentas(cliente.getDni()).get(0);
cuentaDestino = servicioUjaCoin.verCuentas(cliente2.getDni()).get(0);
// Listar movimientos de la cuenta origen
List<Movimiento> movimientos = servicioUjaCoin.listarMovimientosDesde(cuentaOrigen.getNum(), LocalDateTime.MIN);
Assertions.assertThat(movimientos).hasSize(2);
Assertions.assertThat(movimientos.get(1)).isInstanceOf(TransferenciaEmitida.class);
Assertions.assertThat(cuentaOrigen.getSaldo()).isEqualTo(500);
Assertions.assertThat(cuentaDestino.listarMovimientos()).hasSize(1);
Assertions.assertThat(cuentaDestino.listarMovimientos().get(0)).isInstanceOf(TransferenciaRecibida.class);
// Listar movimientos de la cuenta destino
movimientos = servicioUjaCoin.listarMovimientosDesde(cuentaDestino.getNum(), LocalDateTime.MIN);
Assertions.assertThat(movimientos).hasSize(1);
Assertions.assertThat(movimientos.get(0)).isInstanceOf(TransferenciaRecibida.class);
Assertions.assertThat(cuentaDestino.getSaldo()).isEqualTo(500);
}
}
@BeforeEach
void limpiarBaseDatos() {
limpiadorBaseDatos.limpiar();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment