Solución:
los @Nested
La anotación le permite tener una clase interna que es esencialmente una clase de prueba, lo que le permite agrupar varias clases de prueba bajo el mismo padre (con la misma inicialización).
Simplemente no entiendo por qué necesitamos tener una clase de prueba anidada en nuestra prueba.
@Nested
tiene mucho sentido organizar grandes clases de prueba.
Caso de uso típico
Muy a menudo, los equipos de desarrolladores definen una clase de prueba por clase para probar. Esa es una buena práctica compartida, pero también puede hacer que su clase de prueba sea muy grande y contar varios cientos de líneas. De hecho, puede tener clases para probar con múltiples métodos para probar, múltiples escenarios para cada uno y también algunos pasos de inicialización requeridos en los métodos de prueba unitaria para probar los escenarios.
Todos estos naturalmente aumentarán el tamaño de la clase de prueba.
Por encima de un umbral (tal vez 500 líneas o aproximadamente), es legítimo preguntarse si se necesita una refactorización.
Una clase grande (clase de prueba o no), incluso bien organizada, es más difícil de leer y mantener que varias clases que agrupan cosas con alta cohesión / relación entre ellas.
En los casos de pruebas unitarias, en algún momento puede ser peor porque es posible que no encuentre un escenario de prueba y escriba uno nuevo mientras existía, pero no logró encontrarlo porque la clase de prueba es grande.
@Nested
: la solución
@Nested
aborda este problema al brindar la posibilidad de agrupar múltiples métodos de prueba dentro de múltiples clases anidadas de una clase de prueba principal (externa).
Los métodos de prueba de todas las clases anidadas definidas en la clase de prueba principal (externa) se manejan como cualquier método de prueba. Entonces @BeforeEach
, @AfterEach
, @ExtendWith
… se aplican para todos ellos.
La única excepción es @BeforeAll
y @AfterAll
:
Solo las clases anidadas no estáticas (es decir, las clases internas) pueden servir como
@Nested
clases de prueba. El anidamiento puede ser arbitrariamente profundo y esas clases internas se consideran miembros de pleno derecho de la familia de clases de prueba con una excepción:@BeforeAll
y@AfterAll
Los métodos no funcionan de forma predeterminada. La razón es que Java no permite miembros estáticos en clases internas. Sin embargo, esta restricción se puede eludir anotando un@Nested
clase de prueba con
@TestInstance(Lifecycle.PER_CLASS
) (consulte Ciclo de vida de la instancia de prueba).
Utilizando @Nested
combinado con @DisplayName
eso toma un String
El valor se vuelve aún más fino ya que el nombre para mostrar se usará para informes de prueba en IDE y herramientas de compilación y puede contener espacios, caracteres especiales e incluso emoji.
Ejemplo
tengo un FooService
con múltiples métodos y múltiples escenarios. Puedo agrupar escenarios de la misma preocupación dentro de clases anidadas de la clase de prueba unitaria.
Aquí elijo el método para probar para agruparlos (así que agrupo por escenario) pero el discriminador podría ser otra cosa si tiene sentido.
Por ejemplo :
public class FooServiceTest {
Foo foo;
// invoked for ALL test methods
@BeforeEach
public void beforeEach() {
Foo foo = new Foo(...);
}
@Nested
@DisplayName("findWith methods")
class FindMethods {
@Test
void findWith_when_X() throws Exception {
//...
foo.findWith(...);
//...
}
@Test
void findWith_when_Y() throws Exception {
//...
foo.findWith(...);
//...
}
@Test
void findWith_when_Z() throws Exception {
//...
foo.findWith(...);
//...
}
}
@Nested
@DisplayName("findAll methods")
class FindAllMethods {
@Test
void findAll_when_X() throws Exception {
//...
foo.findAll(...);
//...
}
@Test
void findAll_when_Y() throws Exception {
//...
foo.findAll(...);
//...
}
@Test
void findAll_when_Z() throws Exception {
//...
foo.findAll(...);
//...
}
}
@Nested
@DisplayName("computeBar methods")
class ComputeBarMethods {
//...
}
@Nested
@DisplayName("saveOrUpdate methods")
class SaveOrUpdateMethods {
//...
}
}
Representaciones de muestra en el IDE
Los métodos secundarios de Nesteds se pliegan de forma predeterminada:
En caso de que la prueba falle o bajo demanda, puede desplegar métodos secundarios de Nesteds:
Todas mis pruebas necesitan un servidor de base de datos en ejecución. La mayoría de mis pruebas también necesitan una tabla de Usuarios en la base de datos, para poder iniciar sesión. Además de eso, algunas pruebas necesitan la tabla de Amigos para poder iniciar sesión y consultar amigos.
Cada recurso tiene una configuración y un desmontaje. Tengo que iniciar y detener el servidor, crear y eliminar tablas.
Con la anotación @Nested, puedo agrupar mis pruebas en una jerarquía de clases anidadas para que cada prueba obtenga la configuración y el desmontaje de todas las pruebas en la jerarquía.
Esta idea de pruebas de anidamiento se popularizó en Ruby. En Java se implementa para Junit 4 mediante HierarchicalContextRunner. Vea la justificación en su página https://github.com/bechte/junit-hierarchicalcontextrunner/wiki.