Pruebas de lógica de negocio
Configuración con JUnit y Spring
Sección titulada «Configuración con JUnit y Spring»@DataJpaTest@Transactional@Import(CompanyService.class)public class CompanyServiceTest { @Autowired private CompanyService companyService;
@Autowired private TestEntityManager entityManager;
private PodamFactory factory = new PodamFactoryImpl(); private List<CompanyEntity> companyList = new ArrayList<>();}@DataJpaTestcarga la configuración necesaria para JPA, sin servidor web.@Transactionalejecuta cada prueba en una transacción que se revierte al terminar.@Import(CompanyService.class)incorpora al contexto el servicio bajo prueba.@Autowiredinyecta el servicio y elTestEntityManager.
TestEntityManager
Sección titulada «TestEntityManager»Permite preparar y verificar la base de datos de pruebas sin pasar por el servicio que se evalúa:
persist(entity)inserta datos.find(Class, id)busca una entidad.createQuery(...)ejecuta consultas.- la limpieza entre pruebas garantiza aislamiento.
El servicio usa su repository; la prueba usa TestEntityManager directamente para que un error en el servicio no contamine la preparación de datos.
setUp y ciclo de vida
Sección titulada «setUp y ciclo de vida»@BeforeEach ejecuta setUp() antes de cada test. JUnit no garantiza un orden, por lo que cada prueba debe iniciar con un estado conocido.
@BeforeEach: limpiar la base e insertar datos frescos.@Test: ejecutar el escenario con esos datos.@AfterEach, si existe: ejecutar tareas posteriores. Normalmente el rollback de@Transactionalbasta.- Repetir el ciclo para cada método de prueba.
Explora el ciclo y los escenarios de una prueba
Compara la preparación común con un caso feliz y una regla violada.
Limpiar datos
clearData elimina el estado anterior mediante una consulta JPQL.
delete from CompanyEntity@BeforeEachvoid setUp() { clearData(); insertData();}
private void clearData() { entityManager.getEntityManager() .createQuery("delete from CompanyEntity") .executeUpdate();}
private void insertData() { for (int i = 0; i < 3; i++) { CompanyEntity entity = factory.manufacturePojo(CompanyEntity.class); entityManager.persist(entity); companyList.add(entity); }}La consulta de limpieza es JPQL, no SQL nativo. Si hay cinco métodos @Test, setUp() se ejecuta cinco veces.
Podam genera objetos Java con datos aleatorios para reducir la preparación manual:
CompanyEntity entity = factory.manufacturePojo(CompanyEntity.class);En relaciones bidireccionales puede producir un ciclo infinito al intentar construir ambos lados repetidamente. @PodamExclude excluye de la generación el atributo que cierra el ciclo. Después se asignan manualmente las relaciones que el escenario necesita.
Buenas prácticas: usar una sola fábrica por clase, modificar explícitamente los datos relevantes para el caso, excluir relaciones problemáticas y persistir las entidades en el orden que exigen sus dependencias.
Escenarios positivos y negativos
Sección titulada «Escenarios positivos y negativos»Un escenario positivo verifica el caso feliz:
@Testvoid testCreateCompany() throws EntityNotFoundException, IllegalOperationException { CompanyEntity newEntity = factory.manufacturePojo(CompanyEntity.class);
CompanyEntity result = companyService.createCompany(newEntity); assertNotNull(result);
CompanyEntity entity = entityManager.find( CompanyEntity.class, result.getId()); assertEquals(newEntity.getName(), entity.getName());}Un escenario negativo verifica una regla y la excepción esperada:
@Testvoid testCreateInvalidCompany() { assertThrows(IllegalOperationException.class, () -> { CompanyEntity newEntity = factory.manufacturePojo(CompanyEntity.class); newEntity.setName(companyList.get(0).getName()); companyService.createCompany(newEntity); });}La estrategia mínima es un caso positivo y un caso negativo por cada regla de negocio. Si un método valida tres reglas, requiere al menos cuatro pruebas.