Pruebas con Java y Spring
Rafael Gutiérrez (rafael.gutierrez@encora.com)
Encora
Septiembre 2025
¿Por qué probar el software?
En general:
● El sistema cumple con los requerimientos (el qué) y especificaciones (el cómo).
● Encontrar errores antes de llegar a producción.
● Prevenir que nuevos cambios no rompan funcionalidad existente (regresión).
● Reducción de costos.
¿Cómo Software Developer?
● Confianza para realizar refactoring.
● Código bien probado es fácil de mantener.
● ¡Documentación viva!
● Colaboración de equipo
● Integración continua: Habilita el uso de flujos de despliegue automatizados confiables.
Pirámide de pruebas
Antipatrón de la pirámide: el cono de helado
JUnit
JUnit 5 - intro
● 1997 - Inventado durante un vuelo de Europa a EUA por Kent Beck y Erich Gamma
○ Kent Beck - XP, Agile Manifesto
○ Erich Gamma - uno de los autores del libro de patrones de diseño
● JUnit 5 en 2017
● Jars
○ Jupiter (test API)
○ Platform (correr las pruebas)
○ Vintage (soporte al JUnit “viejo”)
● JUnit 6 muy pronto
JUnit 5 - ciclo de vida
● Instancia por método de prueba: ayuda a mantener las pruebas aisladas.
○ @TestInstance(Lifecycle.PER_METHOD), @TestInstance(Lifecycle.PER_CLASS)
● Ciclo de vida
○ @Test
○ @BeforeEach
○ @AfterEach
○ @BeforeAll
○ @AfterAll
● @DisplayName
● @Disabled
● @Order
● Demo: MyFirstTestExampleTest, LifecycleExampleTest
JUnit 5 - assertions y assumptions
● Assertions: Ayudan a “verificar” la ejecución de la prueba.
● Métodos estáticos de org.junit.jupiter.api.Assertions.*:
○ assertEquals: verifica igualdad
○ assertTrue/assertFalse: Verifica que la condición se cumpla o no.
○ assertNull/assertNotNull: Verifica que la referencia sea o no nula.
○ assertThrows: Verifica que se tire una excepción al ejecutar un método.
○ assertAll: agrupa verificaciones
○ assertTimeout: valida tiempos de ejecución
○ etc.
● Assumptions: Usadas cuando no tiene sentido continuar con la ejecución si no hay condiciones adecuadas.
● Métodos estáticos de org.junit.jupiter.api.Assumptions.*:
○ assumeTrue/assumeFalse
○ assumeThat
○ etc.
● Demo: TimeTranslatorTest
JUnit 5 - Pruebas parametrizadas
● Pruebas con la misma estructura donde solo varían los datos de entrada.
● @ParameterizedTest: a nivel método
● @ParameterizedClass: a nivel de clase (experimental)
● @ValueSource - valores fijos
● @EnumSource - enumeraciones
● @MethodSource - un método estático provee valores.
● @FieldSource - un atributo estático provee valores.
● @CvsSource, @CvsFileSource - formato CVS
● @ArgumentsSource - clase implementando ArgumentsProvider
● Mismo ciclo de vida que @Test.
● Demo: TimeTranslatorParameterizedTest
JUnit 5 - Pruebas dinámicas
● @TestFactory
● Similares a las pruebas parametrizadas
● Ciclo de vida distinto, solo un @BeforeEach, @AfterEach por todo el conjunto de pruebas.
● Útiles cuando las pruebas no pueden ser expresadas en tiempo de compilación y se
necesita “crearlas” en tiempo de ejecución.
● Son fábrica de pruebas generadas en “runtime”.
● Demo: TimeTranslatorDynamicTest
JUnit - Pruebas anidadas
● @Nested
● Ofrecen más capacidades de expresar relaciones entre grupos de pruebas.
● Hacen uso de clases anidadas.
● Facilitan pensar en la estructura de la prueba como una jerarquía.
● “A something, when X and Y happen, and Z is present, A should be ...”
● Demo: ActivityControllerSpringBootTest vs ActivityControllerSpringBootNestedTest
Hamcrest y AssertJ
● La biblioteca de assertions de JUnit es buena, pero, IMHO, no suficiente.
● Las pruebas deben comunicar su intención claramente.
● Hamcrest: biblioteca de “matchers” que pueden ser combinados para expresar mejor la
“intención” de los assertions.
● AssertJ: biblioteca de assertions “fluidas”
● Mejores mensajes de error
● Demo: BetterAssertionsDemoTest
Test Doubles y Mocking
Frameworks
Dobles de pruebas (1)
● “Impostores” que ayudan a aislar el código
que se quiere probar
● Más rápidos que usar una implementación
real.
● Hacen la ejecución de la prueba determinista.
● Simulan condiciones especiales
● Exponen información oculta que ayuda a
validar.
Dobles de pruebas (2)
● Test Stub - Dan respuestas predefinidas, útiles para comportamientos deterministas.
● Test Spy - “graban” información al ser llamados, utiles para
● Mock Object - pre-programados con “expectativas”. Tiran errores en caso de no recibir las
llamadas que se esperan (mock frameworks)
● Fake Object - implementaciones que funcionan, pero toman “shortcuts” (ejemplo, una in-memory
database)
● Dummy* - solo para “rellenar”, aunque no son realmente usados.
*Variación de Fake Object
Mock Frameworks
● Mockito, EasyMock, PowerMock, etc.
● Funcionalidades:
● Creación de “dobles de pruebas” (completos y parciales)
● Especifican comportamiento
● Control en los valores de retorno
● Control en el “lanzamiento” de excepciones
● Comparación “Matching” de argumentos
● Verificación de llamadas
● “Espiar” objetos, llamadas y argumentos
Mockito y Test Stubs
● Reemplaza objetos reales con objetos específicos de prueba.
● Ayuda a devolver “entradas indirectas” deseadas desde otros componentes al SUT (Sistema bajo prueba, System
under test).
● Responder: Devuelve “entradas indirectas” válidas.
● Saboteur: Devuelve “entradas indirectas” inválidas.
● Temporary Test Stub: usado cuando el componente del cual se depende aún no está listo (está en desarrollo).
● Entity Chain Snipping: como un Responder pero para reemplazar algún objeto complejo de crear que usa el SUT.
● Hard-Coded Test Stub
● Configurable Test Stub
● Procedural Test Stub
● Demo: MockitoTestStubDemoTest
Mockito y Test Spies
● Ayuda a verificar el “comportamiento”.
● Ayuda a capturar las “salidas indirectas” del SUT a otros componentes, para verificarlos después.
● Retrieval Interface: un test double que expone métodos para obtener la información “grabada”.
● Self Shunt: Cuando la misma clase de prueba se instala como el doble de pruebas espía.
● Inner Test Double: Se crea una clase interna anónima como doble de prueba espía.
● Indirect Output Registry
● Ver: MockitoTestSpyDemoTest
Mockito y Mock Objects
● Muy similares a los stubs, pero podemos implementar verificación de “comportamiento”.
● Se reemplaza el objeto real con un doble de pruebas que se puede verificar que fue usado
correctamente por el SUT.
● Diferencia con los stubs: la verificación final.
● Demo: MockitoMockObjectDemoTest
Mockito y Fake Objects
● Ayudan a probar nuestro código cuando los componentes de los que se depende no
existen aún.
● Poder probar nuestro código con componentes más “ligeros” y evitar pruebas lentas.
● Fake Database
● In-Memory Database
● Fake Web Service
● Fake Service Layer
● Demo: ejemplos anteriores
Spring Boot
¡Nada!
● No necesitas levantar el contexto de Spring.
● Inyección de dependencias facilita usar dobles de prueba
Soporte a pruebas de Spring
● El framework de Spring provee soporte de “primera clase” a las pruebas de integración con el módulo spring-test.
● El soporte a pruebas de Spring Boot está en los módulos spring-boot-test y spring-boot-test-autoconfigure.
● Starter: spring-boot-startet-test
○ Incluye bibliotecas como: JUnit 5, Spring Test, AssertJ, Hamcrest, Mockito, JSONassert, JsonPath, Awaitility.
● @SpringBootTest crea un ApplicationContext y/o WebServerApplicationContext
● Pruebas de “capas” con @*Test
● @TestConfiguration
● @ActiveProfiles
● @TestPropertySource
@ExtendWith(MockitoExtension.class), @Mock, @InjectMocks
● Ayuda a probar la capa de servicios.
● Mocks para la capa de repositorios y otros servicios.
● @Mock e @InjectMocks: soporte de Mockito a mocks usando anotaciones para JUnit.
● Demo: ActivityServiceTest
@JsonTest
● Ayuda a probar la serialización y deserialización de objetos.
● Autoconfigura el soporte a JSON mappers de acuerdo a las dependencias.
○ Jackson (el más común)
○ Gson
○ Jsonb
● Se incluye soporte basado en AssertJ para JSONAssert y JsonPath para validar JSON.
○ JSONAssert: verifica JSON como si fueran String
○ JsonPath: navegar un JSON, hacer consultas a JSON
● Se puede usar Hamcrest.
● Demo: ActivityDTOJsonTest
@WebMvcTest
● Ayuda a probar la capa de controllers.
● Autoconfigura Spring MVC
● Escanea solamente @Controller, @ControllerAdvice, @JsonComponent, etc.
● @Component y @ConfigurationProperties no son escaneados.
● Pensado para probar un solo controller por clase de prueba.
● Demo: ActivityControllerWebMvcTest
@DataJpaTest
● Escanea @Entity clases
● Configura repositorios Spring Data JPA
● Si una base de datos embebida está en el classpath, la usa.
○ IMHO, yo prefiero Testcontainers y usar base de datos real.
● Demo: ActivityRepositoryH2DataJpaTest
● Es importante poder ejecutar pruebas de integración sin requerir del despliegue de la aplicación en
servidor u otro tipo de infraestructura que el sistema use.
● Puede levantar un servidor, pero por defecto no lo hace.
● Atributo webEnvironment:
○ MOCK (predeterminado), RANDOM_PORT, DEFINED_PORT, NONE
● @WebTestClient: Usa WebClient internamente y usa una API fluida para verificar respuestas.
● @TestRestTemplate: alternativa al RestTemplate para pruebas integrales
● Demo: ActivityServiceIntegrationTest
● Demo: ActivityControllerSpringBootTest
@SpringBootTest
Testcontainers
● Servicios corriendo dentro de contenedores docker.
● Integrado con JUnit, permite correr un contenedor antes de correr las pruebas.
● Útil para pruebas integrales a servicios backend reales como Postgres, MySQL, MongoDB, Cassandra,
etc.
● Contenedores administrados por Spring como @Bean
● Contenedores administrados por Testcontainers usando las extensiones de JUnit: @Testcontainers,
@Container, @DynamicPropertySource
● Demo: ActivityRepositoryWithTestContainerDataJpaTest
● Demo: ActivityServiceIntegrationTest
Otras anotaciones
● @WebFluxTest
● @GraphQlTest
● @JdbcTest
● @JooqTest
● @DataJdbcTest
● @DataCassandraTest
● @DataCouchbaseTest
● @DataElasticsearchTest
● @DataMongoTest
● @DataNeo4jTest
● @DataRedisTest
● @DataLdapTest
● @RestClientTest
● @WebServiceClientTest
● etc.
Conclusion
¿Qué probar?
● Prueba comportamiento, no implementación.
● Prueba la interfaz pública de los componentes.
● Prueba casos “extremos” (edge cases) y casos de error.
● Prueba lógica de negocio.
● Prueba puntos de integración entre componentes.
● Prueba flujos de negocio.
● ¿Ocurrió un bug? Reproduce el error con una prueba y solo después arregla el issue.
○ Práctica ágil de eXtreme Programming y Test Driven Development. Red-Green-Refactor.
● Usa la cobertura de código para encontrar flujos de negocio no probados.
Buenas prácticas
● Patrón AAA (Arrange, Act, Assert) para mantener las pruebas organizadas y consistentes.
● Probar una sola cosa por método (conceptualmente hablando).
● Cuida tu código de prueba como el código de producción.
● DRY, KISS
● Asegúrate de que la prueba falla.
● Evita aserciones primitivas.
○ Puedes incluso crear tu “biblioteca” de aserciones muy ligada al lenguaje de dominio.
● Código claro, que las pruebas comuniquen bien su “intención”.
● Crea “test fixtures” reutilizables y fáciles de modificar para casos nuevos.
○ Patrón Builder/Factories
“I'm not a great programmer; I'm
just a good programmer with
great habits.”
― Kent Beck
Referencias
https://martinfowler.com/bliki/TestPyramid.html
https://www.james-willett.com/the-evolution-of-the-testing-pyramid/
https://docs.junit.org/current/user-guide/#overview
https://martinfowler.com/bliki/TestDouble.html
https://martinfowler.com/articles/mocksArentStubs.html
https://jsonassert.skyscreamer.org/
https://github.com/json-path/JsonPath
https://hamcrest.org/JavaHamcrest/
https://assertj.github.io/doc/
https://www.baeldung.com/hamcrest-collections-arrays
Libro: xUnit Test Patterns: Refactoring Test Code
https://docs.spring.io/spring-framework/reference/testing.html
https://docs.spring.io/spring-boot/reference/testing/index.html
https://java.testcontainers.org/
https://java.testcontainers.org/test_framework_integration/junit_5/
https://martinfowler.com/bliki/TestCoverage.html

Platica - Pruebas modernas con Java y Spring

  • 1.
    Pruebas con Javay Spring Rafael Gutiérrez (rafael.gutierrez@encora.com) Encora Septiembre 2025
  • 2.
    ¿Por qué probarel software? En general: ● El sistema cumple con los requerimientos (el qué) y especificaciones (el cómo). ● Encontrar errores antes de llegar a producción. ● Prevenir que nuevos cambios no rompan funcionalidad existente (regresión). ● Reducción de costos. ¿Cómo Software Developer? ● Confianza para realizar refactoring. ● Código bien probado es fácil de mantener. ● ¡Documentación viva! ● Colaboración de equipo ● Integración continua: Habilita el uso de flujos de despliegue automatizados confiables.
  • 3.
  • 4.
    Antipatrón de lapirámide: el cono de helado
  • 5.
  • 6.
    JUnit 5 -intro ● 1997 - Inventado durante un vuelo de Europa a EUA por Kent Beck y Erich Gamma ○ Kent Beck - XP, Agile Manifesto ○ Erich Gamma - uno de los autores del libro de patrones de diseño ● JUnit 5 en 2017 ● Jars ○ Jupiter (test API) ○ Platform (correr las pruebas) ○ Vintage (soporte al JUnit “viejo”) ● JUnit 6 muy pronto
  • 7.
    JUnit 5 -ciclo de vida ● Instancia por método de prueba: ayuda a mantener las pruebas aisladas. ○ @TestInstance(Lifecycle.PER_METHOD), @TestInstance(Lifecycle.PER_CLASS) ● Ciclo de vida ○ @Test ○ @BeforeEach ○ @AfterEach ○ @BeforeAll ○ @AfterAll ● @DisplayName ● @Disabled ● @Order ● Demo: MyFirstTestExampleTest, LifecycleExampleTest
  • 8.
    JUnit 5 -assertions y assumptions ● Assertions: Ayudan a “verificar” la ejecución de la prueba. ● Métodos estáticos de org.junit.jupiter.api.Assertions.*: ○ assertEquals: verifica igualdad ○ assertTrue/assertFalse: Verifica que la condición se cumpla o no. ○ assertNull/assertNotNull: Verifica que la referencia sea o no nula. ○ assertThrows: Verifica que se tire una excepción al ejecutar un método. ○ assertAll: agrupa verificaciones ○ assertTimeout: valida tiempos de ejecución ○ etc. ● Assumptions: Usadas cuando no tiene sentido continuar con la ejecución si no hay condiciones adecuadas. ● Métodos estáticos de org.junit.jupiter.api.Assumptions.*: ○ assumeTrue/assumeFalse ○ assumeThat ○ etc. ● Demo: TimeTranslatorTest
  • 9.
    JUnit 5 -Pruebas parametrizadas ● Pruebas con la misma estructura donde solo varían los datos de entrada. ● @ParameterizedTest: a nivel método ● @ParameterizedClass: a nivel de clase (experimental) ● @ValueSource - valores fijos ● @EnumSource - enumeraciones ● @MethodSource - un método estático provee valores. ● @FieldSource - un atributo estático provee valores. ● @CvsSource, @CvsFileSource - formato CVS ● @ArgumentsSource - clase implementando ArgumentsProvider ● Mismo ciclo de vida que @Test. ● Demo: TimeTranslatorParameterizedTest
  • 10.
    JUnit 5 -Pruebas dinámicas ● @TestFactory ● Similares a las pruebas parametrizadas ● Ciclo de vida distinto, solo un @BeforeEach, @AfterEach por todo el conjunto de pruebas. ● Útiles cuando las pruebas no pueden ser expresadas en tiempo de compilación y se necesita “crearlas” en tiempo de ejecución. ● Son fábrica de pruebas generadas en “runtime”. ● Demo: TimeTranslatorDynamicTest
  • 11.
    JUnit - Pruebasanidadas ● @Nested ● Ofrecen más capacidades de expresar relaciones entre grupos de pruebas. ● Hacen uso de clases anidadas. ● Facilitan pensar en la estructura de la prueba como una jerarquía. ● “A something, when X and Y happen, and Z is present, A should be ...” ● Demo: ActivityControllerSpringBootTest vs ActivityControllerSpringBootNestedTest
  • 12.
    Hamcrest y AssertJ ●La biblioteca de assertions de JUnit es buena, pero, IMHO, no suficiente. ● Las pruebas deben comunicar su intención claramente. ● Hamcrest: biblioteca de “matchers” que pueden ser combinados para expresar mejor la “intención” de los assertions. ● AssertJ: biblioteca de assertions “fluidas” ● Mejores mensajes de error ● Demo: BetterAssertionsDemoTest
  • 13.
    Test Doubles yMocking Frameworks
  • 14.
    Dobles de pruebas(1) ● “Impostores” que ayudan a aislar el código que se quiere probar ● Más rápidos que usar una implementación real. ● Hacen la ejecución de la prueba determinista. ● Simulan condiciones especiales ● Exponen información oculta que ayuda a validar.
  • 15.
    Dobles de pruebas(2) ● Test Stub - Dan respuestas predefinidas, útiles para comportamientos deterministas. ● Test Spy - “graban” información al ser llamados, utiles para ● Mock Object - pre-programados con “expectativas”. Tiran errores en caso de no recibir las llamadas que se esperan (mock frameworks) ● Fake Object - implementaciones que funcionan, pero toman “shortcuts” (ejemplo, una in-memory database) ● Dummy* - solo para “rellenar”, aunque no son realmente usados. *Variación de Fake Object
  • 16.
    Mock Frameworks ● Mockito,EasyMock, PowerMock, etc. ● Funcionalidades: ● Creación de “dobles de pruebas” (completos y parciales) ● Especifican comportamiento ● Control en los valores de retorno ● Control en el “lanzamiento” de excepciones ● Comparación “Matching” de argumentos ● Verificación de llamadas ● “Espiar” objetos, llamadas y argumentos
  • 17.
    Mockito y TestStubs ● Reemplaza objetos reales con objetos específicos de prueba. ● Ayuda a devolver “entradas indirectas” deseadas desde otros componentes al SUT (Sistema bajo prueba, System under test). ● Responder: Devuelve “entradas indirectas” válidas. ● Saboteur: Devuelve “entradas indirectas” inválidas. ● Temporary Test Stub: usado cuando el componente del cual se depende aún no está listo (está en desarrollo). ● Entity Chain Snipping: como un Responder pero para reemplazar algún objeto complejo de crear que usa el SUT. ● Hard-Coded Test Stub ● Configurable Test Stub ● Procedural Test Stub ● Demo: MockitoTestStubDemoTest
  • 18.
    Mockito y TestSpies ● Ayuda a verificar el “comportamiento”. ● Ayuda a capturar las “salidas indirectas” del SUT a otros componentes, para verificarlos después. ● Retrieval Interface: un test double que expone métodos para obtener la información “grabada”. ● Self Shunt: Cuando la misma clase de prueba se instala como el doble de pruebas espía. ● Inner Test Double: Se crea una clase interna anónima como doble de prueba espía. ● Indirect Output Registry ● Ver: MockitoTestSpyDemoTest
  • 19.
    Mockito y MockObjects ● Muy similares a los stubs, pero podemos implementar verificación de “comportamiento”. ● Se reemplaza el objeto real con un doble de pruebas que se puede verificar que fue usado correctamente por el SUT. ● Diferencia con los stubs: la verificación final. ● Demo: MockitoMockObjectDemoTest
  • 20.
    Mockito y FakeObjects ● Ayudan a probar nuestro código cuando los componentes de los que se depende no existen aún. ● Poder probar nuestro código con componentes más “ligeros” y evitar pruebas lentas. ● Fake Database ● In-Memory Database ● Fake Web Service ● Fake Service Layer ● Demo: ejemplos anteriores
  • 21.
  • 22.
    ¡Nada! ● No necesitaslevantar el contexto de Spring. ● Inyección de dependencias facilita usar dobles de prueba
  • 23.
    Soporte a pruebasde Spring ● El framework de Spring provee soporte de “primera clase” a las pruebas de integración con el módulo spring-test. ● El soporte a pruebas de Spring Boot está en los módulos spring-boot-test y spring-boot-test-autoconfigure. ● Starter: spring-boot-startet-test ○ Incluye bibliotecas como: JUnit 5, Spring Test, AssertJ, Hamcrest, Mockito, JSONassert, JsonPath, Awaitility. ● @SpringBootTest crea un ApplicationContext y/o WebServerApplicationContext ● Pruebas de “capas” con @*Test ● @TestConfiguration ● @ActiveProfiles ● @TestPropertySource
  • 24.
    @ExtendWith(MockitoExtension.class), @Mock, @InjectMocks ●Ayuda a probar la capa de servicios. ● Mocks para la capa de repositorios y otros servicios. ● @Mock e @InjectMocks: soporte de Mockito a mocks usando anotaciones para JUnit. ● Demo: ActivityServiceTest
  • 25.
    @JsonTest ● Ayuda aprobar la serialización y deserialización de objetos. ● Autoconfigura el soporte a JSON mappers de acuerdo a las dependencias. ○ Jackson (el más común) ○ Gson ○ Jsonb ● Se incluye soporte basado en AssertJ para JSONAssert y JsonPath para validar JSON. ○ JSONAssert: verifica JSON como si fueran String ○ JsonPath: navegar un JSON, hacer consultas a JSON ● Se puede usar Hamcrest. ● Demo: ActivityDTOJsonTest
  • 26.
    @WebMvcTest ● Ayuda aprobar la capa de controllers. ● Autoconfigura Spring MVC ● Escanea solamente @Controller, @ControllerAdvice, @JsonComponent, etc. ● @Component y @ConfigurationProperties no son escaneados. ● Pensado para probar un solo controller por clase de prueba. ● Demo: ActivityControllerWebMvcTest
  • 27.
    @DataJpaTest ● Escanea @Entityclases ● Configura repositorios Spring Data JPA ● Si una base de datos embebida está en el classpath, la usa. ○ IMHO, yo prefiero Testcontainers y usar base de datos real. ● Demo: ActivityRepositoryH2DataJpaTest
  • 28.
    ● Es importantepoder ejecutar pruebas de integración sin requerir del despliegue de la aplicación en servidor u otro tipo de infraestructura que el sistema use. ● Puede levantar un servidor, pero por defecto no lo hace. ● Atributo webEnvironment: ○ MOCK (predeterminado), RANDOM_PORT, DEFINED_PORT, NONE ● @WebTestClient: Usa WebClient internamente y usa una API fluida para verificar respuestas. ● @TestRestTemplate: alternativa al RestTemplate para pruebas integrales ● Demo: ActivityServiceIntegrationTest ● Demo: ActivityControllerSpringBootTest @SpringBootTest
  • 29.
    Testcontainers ● Servicios corriendodentro de contenedores docker. ● Integrado con JUnit, permite correr un contenedor antes de correr las pruebas. ● Útil para pruebas integrales a servicios backend reales como Postgres, MySQL, MongoDB, Cassandra, etc. ● Contenedores administrados por Spring como @Bean ● Contenedores administrados por Testcontainers usando las extensiones de JUnit: @Testcontainers, @Container, @DynamicPropertySource ● Demo: ActivityRepositoryWithTestContainerDataJpaTest ● Demo: ActivityServiceIntegrationTest
  • 30.
    Otras anotaciones ● @WebFluxTest ●@GraphQlTest ● @JdbcTest ● @JooqTest ● @DataJdbcTest ● @DataCassandraTest ● @DataCouchbaseTest ● @DataElasticsearchTest ● @DataMongoTest ● @DataNeo4jTest ● @DataRedisTest ● @DataLdapTest ● @RestClientTest ● @WebServiceClientTest ● etc.
  • 31.
  • 32.
    ¿Qué probar? ● Pruebacomportamiento, no implementación. ● Prueba la interfaz pública de los componentes. ● Prueba casos “extremos” (edge cases) y casos de error. ● Prueba lógica de negocio. ● Prueba puntos de integración entre componentes. ● Prueba flujos de negocio. ● ¿Ocurrió un bug? Reproduce el error con una prueba y solo después arregla el issue. ○ Práctica ágil de eXtreme Programming y Test Driven Development. Red-Green-Refactor. ● Usa la cobertura de código para encontrar flujos de negocio no probados.
  • 33.
    Buenas prácticas ● PatrónAAA (Arrange, Act, Assert) para mantener las pruebas organizadas y consistentes. ● Probar una sola cosa por método (conceptualmente hablando). ● Cuida tu código de prueba como el código de producción. ● DRY, KISS ● Asegúrate de que la prueba falla. ● Evita aserciones primitivas. ○ Puedes incluso crear tu “biblioteca” de aserciones muy ligada al lenguaje de dominio. ● Código claro, que las pruebas comuniquen bien su “intención”. ● Crea “test fixtures” reutilizables y fáciles de modificar para casos nuevos. ○ Patrón Builder/Factories
  • 34.
    “I'm not agreat programmer; I'm just a good programmer with great habits.” ― Kent Beck
  • 35.
    Referencias https://martinfowler.com/bliki/TestPyramid.html https://www.james-willett.com/the-evolution-of-the-testing-pyramid/ https://docs.junit.org/current/user-guide/#overview https://martinfowler.com/bliki/TestDouble.html https://martinfowler.com/articles/mocksArentStubs.html https://jsonassert.skyscreamer.org/ https://github.com/json-path/JsonPath https://hamcrest.org/JavaHamcrest/ https://assertj.github.io/doc/ https://www.baeldung.com/hamcrest-collections-arrays Libro: xUnit TestPatterns: Refactoring Test Code https://docs.spring.io/spring-framework/reference/testing.html https://docs.spring.io/spring-boot/reference/testing/index.html https://java.testcontainers.org/ https://java.testcontainers.org/test_framework_integration/junit_5/ https://martinfowler.com/bliki/TestCoverage.html