Commit c0779679 by Antonio Rueda

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

parent e5609ca6
...@@ -39,7 +39,6 @@ ...@@ -39,7 +39,6 @@
<artifactId>spring-boot-starter-validation</artifactId> <artifactId>spring-boot-starter-validation</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
...@@ -51,18 +50,6 @@ ...@@ -51,18 +50,6 @@
<artifactId>junit-jupiter</artifactId> <artifactId>junit-jupiter</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </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>
-->
</dependencies> </dependencies>
<build> <build>
......
...@@ -14,7 +14,7 @@ import org.springframework.context.ApplicationContext; ...@@ -14,7 +14,7 @@ import org.springframework.context.ApplicationContext;
* *
* @author admin * @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") @EntityScan(basePackages="es.ujaen.dae.ujacoin.entidades")
public class UjaCoinApp { public class UjaCoinApp {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
......
...@@ -13,6 +13,7 @@ import java.util.ArrayList; ...@@ -13,6 +13,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import javax.persistence.CascadeType;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.FetchType; import javax.persistence.FetchType;
import javax.persistence.Id; import javax.persistence.Id;
...@@ -58,7 +59,7 @@ public class Cliente implements Serializable { ...@@ -58,7 +59,7 @@ public class Cliente implements Serializable {
/** Tarjetas asociadas al cliente (no tiene por qué ser el titular */ /** 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") @JoinColumn(name="cliente_dni")
List<Tarjeta> tarjetas; List<Tarjeta> tarjetas;
......
...@@ -13,6 +13,7 @@ import java.util.ArrayList; ...@@ -13,6 +13,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.persistence.CascadeType;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
...@@ -45,10 +46,13 @@ public class Cuenta { ...@@ -45,10 +46,13 @@ public class Cuenta {
Cliente titular; Cliente titular;
/** Lista de movimientos */ /** Lista de movimientos */
@OneToMany @OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="cuenta_num") @JoinColumn(name="cuenta_num")
List<Movimiento> movimientos; List<Movimiento> movimientos;
public Cuenta() {
}
public Cuenta(String num, Cliente titular) { public Cuenta(String num, Cliente titular) {
this.num = num; this.num = num;
this.titular = titular; this.titular = titular;
...@@ -91,17 +95,21 @@ public class Cuenta { ...@@ -91,17 +95,21 @@ public class Cuenta {
* @return la lista de movimientos dentro del intervalo de fechas indicado * @return la lista de movimientos dentro del intervalo de fechas indicado
*/ */
public List<Movimiento> listarMovimientosDesdeHasta(LocalDateTime fechaHoraDesde, LocalDateTime fechaHoraHasta) { public List<Movimiento> listarMovimientosDesdeHasta(LocalDateTime fechaHoraDesde, LocalDateTime fechaHoraHasta) {
LocalDateTime fechaHoraDesdeConsulta = Optional.ofNullable(fechaHoraHasta).orElseGet( if (fechaHoraDesde == null) {
() -> {
LocalDateTime ahora = LocalDateTime.now(); LocalDateTime ahora = LocalDateTime.now();
return ahora.minusDays(ahora.getDayOfMonth() - 1); fechaHoraDesde = ahora.minusDays(ahora.getDayOfMonth() - 1);
} }
);
LocalDateTime fechaHoraHastaConsulta = Optional.ofNullable(fechaHoraHasta).orElse(LocalDateTime.now()); if (fechaHoraHasta == null) {
fechaHoraHasta = LocalDateTime.now();
}
final LocalDateTime desde = fechaHoraDesde;
final LocalDateTime hasta = fechaHoraHasta;
return movimientos.stream().filter(m -> return movimientos.stream().filter(m ->
m.getFechaHora().isAfter(fechaHoraDesdeConsulta) && m.getFechaHora().isAfter(desde) &&
m.getFechaHora().isBefore(fechaHoraHastaConsulta) m.getFechaHora().isBefore(hasta)
).collect(Collectors.toList()); ).collect(Collectors.toList());
} }
......
...@@ -31,7 +31,6 @@ public abstract class Movimiento implements Serializable { ...@@ -31,7 +31,6 @@ public abstract class Movimiento implements Serializable {
@PastOrPresent @PastOrPresent
LocalDateTime fechaHora; LocalDateTime fechaHora;
/** Importe del movimiento. Los valores negativos representan retiradas de dinero */ /** Importe del movimiento. Los valores negativos representan retiradas de dinero */
@Positive
float importe; float importe;
public Movimiento() { 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 ...@@ -4,7 +4,7 @@ spring.datasource.url: jdbc:mysql://localhost:33060/ujacoin
spring.datasource.username: ujacoin spring.datasource.username: ujacoin
spring.datasource.password: secret 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 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; ...@@ -9,37 +9,40 @@ import es.ujaen.dae.ujacoin.entidades.Cliente;
import es.ujaen.dae.ujacoin.entidades.Cuenta; import es.ujaen.dae.ujacoin.entidades.Cuenta;
import es.ujaen.dae.ujacoin.entidades.Tarjeta; import es.ujaen.dae.ujacoin.entidades.Tarjeta;
import es.ujaen.dae.ujacoin.entidades.movimientos.Ingreso; 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.TransferenciaEmitida;
import es.ujaen.dae.ujacoin.entidades.movimientos.TransferenciaRecibida; import es.ujaen.dae.ujacoin.entidades.movimientos.TransferenciaRecibida;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import javax.validation.ConstraintViolationException; import javax.validation.ConstraintViolationException;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.MethodMode;
/** /**
* *
* @author ajrueda * @author ajrueda
*/ */
//@Disabled // @Disabled
@SpringBootTest(classes = es.ujaen.dae.ujacoin.app.UjaCoinApp.class) @SpringBootTest(classes = es.ujaen.dae.ujacoin.app.UjaCoinApp.class)
public class ServicioUjaCoinTest { public class ServicioUjaCoinTest {
@Autowired @Autowired
ServicioUjaCoin servicioUjaCoin; ServicioUjaCoin servicioUjaCoin;
@Autowired
ServicioLimpiadoBaseDatos limpiadorBaseDatos;
@Test @Test
public void testAccesoServicioUjaCoin() { public void testAccesoServicioUjaCoin() {
Assertions.assertThat(servicioUjaCoin).isNotNull(); Assertions.assertThat(servicioUjaCoin).isNotNull();
} }
@Test @Test
@DirtiesContext(methodMode = MethodMode.AFTER_METHOD)
public void testAltaClienteInvalido() { public void testAltaClienteInvalido() {
// Cliente con e-mail incorrecto!!! // Cliente con e-mail incorrecto!!!
Cliente cliente = new Cliente( Cliente cliente = new Cliente(
...@@ -57,7 +60,6 @@ public class ServicioUjaCoinTest { ...@@ -57,7 +60,6 @@ public class ServicioUjaCoinTest {
} }
@Test @Test
@DirtiesContext(methodMode = MethodMode.AFTER_METHOD)
public void testAltaYLoginClienteCuenta() { public void testAltaYLoginClienteCuenta() {
Cliente cliente = new Cliente( Cliente cliente = new Cliente(
"11995667D", "11995667D",
...@@ -68,15 +70,60 @@ public class ServicioUjaCoinTest { ...@@ -68,15 +70,60 @@ public class ServicioUjaCoinTest {
"jee@gmail.com", "jee@gmail.com",
"clave"); "clave");
Cuenta cuenta = servicioUjaCoin.altaCliente(cliente); servicioUjaCoin.altaCliente(cliente);
Optional<Cliente> clienteLogin = servicioUjaCoin.loginCliente(cliente.getDni(), "clave"); Optional<Cliente> clienteLogin = servicioUjaCoin.loginCliente(cliente.getDni(), "clave");
Assertions.assertThat(clienteLogin.isPresent()).isTrue(); 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
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 @Test
@DirtiesContext(methodMode = MethodMode.AFTER_METHOD)
public void testIngreso() { public void testIngreso() {
// Registrar cliente y realizar login // Registrar cliente y realizar login
Cliente cliente = new Cliente( Cliente cliente = new Cliente(
...@@ -102,13 +149,14 @@ public class ServicioUjaCoinTest { ...@@ -102,13 +149,14 @@ public class ServicioUjaCoinTest {
// Realizar ingreso y comprobar estado de la cuenta // Realizar ingreso y comprobar estado de la cuenta
servicioUjaCoin.ingreso(cuentas.get(0).getNum(), tarjeta.getNum(), 1000); 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); List<Movimiento> movimientos = servicioUjaCoin.listarMovimientosDesde(cuentas.get(0).getNum(), LocalDateTime.MIN);
Assertions.assertThat(cuentas.get(0).getSaldo()).isEqualTo(1000); Assertions.assertThat(movimientos).hasSize(1);
Assertions.assertThat(movimientos.get(0)).isInstanceOf(Ingreso.class);
Assertions.assertThat(movimientos.get(0).getImporte()).isEqualTo(1000);
} }
@Test @Test
@DirtiesContext(methodMode = MethodMode.AFTER_METHOD)
public void testTransferencia() { public void testTransferencia() {
// Registrar cliente // Registrar cliente
Cliente cliente = new Cliente( Cliente cliente = new Cliente(
...@@ -120,7 +168,7 @@ public class ServicioUjaCoinTest { ...@@ -120,7 +168,7 @@ public class ServicioUjaCoinTest {
"jee@gmail.com", "jee@gmail.com",
"claveyyy"); "claveyyy");
Cuenta cuenta = servicioUjaCoin.altaCliente(cliente); Cuenta cuentaOrigen = servicioUjaCoin.altaCliente(cliente);
// Añadir una tarjeta // Añadir una tarjeta
Tarjeta tarjeta = new Tarjeta("4111111111111111", cliente.getNombre(), LocalDate.of(2022, 12, 1), "365"); Tarjeta tarjeta = new Tarjeta("4111111111111111", cliente.getNombre(), LocalDate.of(2022, 12, 1), "365");
...@@ -128,7 +176,6 @@ public class ServicioUjaCoinTest { ...@@ -128,7 +176,6 @@ public class ServicioUjaCoinTest {
cliente.nuevaTarjeta(tarjeta); cliente.nuevaTarjeta(tarjeta);
// Obtener cuenta y realizar ingreso en cuenta // Obtener cuenta y realizar ingreso en cuenta
Cuenta cuentaOrigen = servicioUjaCoin.verCuentas(cliente.getDni()).get(0);
servicioUjaCoin.ingreso(cuentaOrigen.getNum(), tarjeta.getNum(), 1000); servicioUjaCoin.ingreso(cuentaOrigen.getNum(), tarjeta.getNum(), 1000);
// Crear segundo cliente // Crear segundo cliente
...@@ -146,12 +193,26 @@ public class ServicioUjaCoinTest { ...@@ -146,12 +193,26 @@ public class ServicioUjaCoinTest {
// Realizar transferencia y comprobar movimientos // Realizar transferencia y comprobar movimientos
servicioUjaCoin.transferencia(cuentaOrigen.getNum(), cuentaDestino.getNum(), 500); 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(cuentaOrigen.getSaldo()).isEqualTo(500);
Assertions.assertThat(cuentaDestino.listarMovimientos()).hasSize(1); // Listar movimientos de la cuenta destino
Assertions.assertThat(cuentaDestino.listarMovimientos().get(0)).isInstanceOf(TransferenciaRecibida.class); 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); 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