Junit Dependency Injection For Constructors And Methods
Junit: Dependency Injection for Constructors and Methods
En todas las versiones anteriores de JUnit, no se permitía que los constructores o métodos de prueba tuvieran parámetros (al menos no con las implementaciones estándar de Runner). Como uno de los principales cambios en JUnit Jupiter, ahora se permite que tanto los constructores como los métodos de prueba tengan parámetros. Esto brinda una mayor flexibilidad y permite la Inyección de Dependencias en constructores y métodos.
ParameterResolver define la API para las extensiones de prueba que deseen resolver dinámicamente los parámetros en tiempo de ejecución. Si un constructor de clase de prueba, un método de prueba o un método del ciclo de vida (ver Definiciones) acepta un parámetro, este debe resolverse en tiempo de ejecución mediante un ParameterResolver registrado.
Actualmente, existen tres resolutores integrados que se registran automáticamente.
-
TestInfoParameterResolver: Si un parámetro de constructor o de método es de tipo
TestInfo, elTestInfoParameterResolverproporcionará una instancia deTestInfocorrespondiente al contenedor o prueba actual como valor para el parámetro. ElTestInfopuede usarse para obtener información sobre el contenedor o la prueba actual, como el nombre de la prueba, la clase de prueba, el método de prueba y las etiquetas asociadas. El nombre de la prueba puede ser un nombre técnico, como el nombre de la clase de prueba o el nombre del método de prueba, o un nombre personalizado configurado mediante la anotación@DisplayName.TestInfoactúa como un reemplazo directo de la reglaTestNamede JUnit 4. A continuación, se muestra cómo inyectarTestInfoen un método@BeforeAll, en el constructor de una clase de prueba, en un método@BeforeEachy en un método@Test.
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
@DisplayName("TestInfo Demo")
class TestInfoDemo {
@BeforeAll
static void beforeAll(TestInfo testInfo) {
assertEquals("TestInfo Demo", testInfo.getDisplayName());
}
TestInfoDemo(TestInfo testInfo) {
String displayName = testInfo.getDisplayName();
assertTrue(displayName.equals("TEST 1") || displayName.equals("test2()"));
}
@BeforeEach
void init(TestInfo testInfo) {
String displayName = testInfo.getDisplayName();
assertTrue(displayName.equals("TEST 1") || displayName.equals("test2()"));
}
@Test
@DisplayName("TEST 1")
@Tag("my-tag")
void test1(TestInfo testInfo) {
assertEquals("TEST 1", testInfo.getDisplayName());
assertTrue(testInfo.getTags().contains("my-tag"));
}
@Test
void test2() {
}
}
-
RepetitionExtension: Si un parámetro de método en un método anotado con
@RepeatedTest,@BeforeEacho@AfterEaches de tipoRepetitionInfo, laRepetitionExtensionproporcionará una instancia deRepetitionInfo. Luego,RepetitionInfose puede utilizar para obtener información sobre la repetición actual, el número total de repeticiones, el número de repeticiones que han fallado y el umbral de fallos correspondiente al@RepeatedTest. Sin embargo, ten en cuenta que laRepetitionExtensionno está registrada fuera del contexto de un@RepeatedTest. Consulta los ejemplos de pruebas repetidas. -
TestReporterParameterResolver: Si un parámetro de constructor o método es de tipo
TestReporter, elTestReporterParameterResolverproporcionará una instancia deTestReporter.TestReporterse puede utilizar para publicar información adicional sobre la ejecución actual de la prueba o adjuntar archivos a ella. Los datos pueden ser consumidos por unTestExecutionListenera través del métodoreportingEntryPublished()ofileEntryPublished(), respectivamente. Esto permite que sean visualizados en los IDEs o incluidos en los informes.En JUnit Jupiter, debes usar
TestReporteren lugar de imprimir información a través destdoutostderrcomo se hacía en JUnit 4. Al usar@RunWith(JUnitPlatform.class), todas las entradas reportadas se mostrarán enstdout. Además, algunos IDEs imprimen las entradas del informe enstdouto las muestran en la interfaz de usuario para los resultados de las pruebas.
class TestReporterDemo {
@Test
void reportSingleValue(TestReporter testReporter) {
testReporter.publishEntry("a status message");
}
@Test
void reportKeyValuePair(TestReporter testReporter) {
testReporter.publishEntry("a key", "a value");
}
@Test
void reportMultipleKeyValuePairs(TestReporter testReporter) {
Map<String, String> values = new HashMap<>();
values.put("user name", "dk38");
values.put("award year", "1974");
testReporter.publishEntry(values);
}
@Test
void reportFiles(TestReporter testReporter, @TempDir Path tempDir) throws Exception {
testReporter.publishFile("test1.txt", MediaType.TEXT_PLAIN_UTF_8,
file -> Files.write(file, singletonList("Test 1")));
Path existingFile = Files.write(tempDir.resolve("test2.txt"), singletonList("Test 2"));
testReporter.publishFile(existingFile, MediaType.TEXT_PLAIN_UTF_8);
testReporter.publishDirectory("test3", dir -> {
Files.write(dir.resolve("nested1.txt"), singletonList("Nested content 1"));
Files.write(dir.resolve("nested2.txt"), singletonList("Nested content 2"));
});
Path existingDir = Files.createDirectory(tempDir.resolve("test4"));
Files.write(existingDir.resolve("nested1.txt"), singletonList("Nested content 1"));
Files.write(existingDir.resolve("nested2.txt"), singletonList("Nested content 2"));
testReporter.publishDirectory(existingDir);
}
}
❕Otros resolvedores de parámetros deben ser habilitados explícitamente registrando las extensiones apropiadas a través de @ExtendWith.
Revisa la RandomParametersExtension para un ejemplo de un ParameterResolver personalizado. Aunque no está destinado a ser utilizado en producción, demuestra la simplicidad y expresividad tanto del modelo de extensiones como del proceso de resolución de parámetros. MyRandomParametersTest demuestra cómo inyectar valores aleatorios en los métodos anotados con @Test.
@ExtendWith(RandomParametersExtension.class)
class MyRandomParametersTest {
@Test
void injectsInteger(@Random int i, @Random int j) {
assertNotEquals(i, j);
}
@Test
void injectsDouble(@Random double d) {
assertEquals(0.0, d, 1.0);
}
}
Para casos de uso del mundo real, consulta el código fuente de MockitoExtension y SpringExtension.
Cuando el tipo de parámetro a inyectar es la única condición para tu ParameterResolver, puedes usar la clase base genérica TypeBasedParameterResolver. El método supportsParameters se implementa por detrás y soporta tipos parametrizados.