· Jose Antonio López  · 3 min lectura

Com carregar un fitxer JSON a Spring Boot per a testing unitari

Carrega qualsevol fitxer JSON en tests unitaris amb Spring Boot, Junit 5 i una anotació personalitzada.

Carrega qualsevol fitxer JSON en tests unitaris amb Spring Boot, Junit 5 i una anotació personalitzada.

Objectiu

Fer una guia real per a carregar un fitxer JSON en tests unitaris de Spring Boot, amb Junit 5 i fent servir l’anotació personalitzada @LoadJsonFile. No he estat capaç de buscar una solució ja feta a Junit 5 o Spring Boot així que he decidit crear-la i compartir-la.

CaracterísticaDescripció
FrameworkSpring Boot 3.5.7
LlenguatgeJava 11 o superior
Tipus d’aplicacióAplicació web REST
Tipus de testTest unitari

Prerequisits

Per a seguir aquest article necessites tenir instal·lat:

Eina/PasEnllaç de descàrrega
JavaDescarregar Java
MavenDescarregar Maven
Projecte amb Spring Boot 2.5.X o superiorCrear projecte Spring Boot
Projecte amb Junit 5Afegir dependència des de Maven Central

Implementació

L’objectiu és fer ús d’una anotació personalitzada @LoadJsonFile que permeti carregar un fitxer JSON en un camp d’una classe de test. Per a fer-ho es necessita fer ús de la interfície TestInstancePostProcessor de Junit 5 que permet modificar la instància de prova abans que s’executi.

Posteriorment, es pot inserir la customització a la classe de test mitjançant l’anotació @ExtendWith que permet registrar extensions personalitzades.

Directori i estructura d’arxius

Els arxius estaran dins de la següent estructura en test:

src/
├── test
    ├── java
       ├── resources
       └── utilites
           ├── LoadJsonFile.java
           └── LoadJsonFilePostProcessor.java

Definició de l’anotació @LoadJsonFile

LoadJsonFile.java
package utilites;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface LoadJsonFile {
    String value();
}

Explicació de l’anotació

  • @Retention(RetentionPolicy.RUNTIME): Indica que l’anotació estarà disponible en temps d’execució.
  • @Target(ElementType.FIELD): L’anotació només es pot aplicar a camps d’una classe.
  • String value():Accepta la ruta del fitxer JSON com un valor de cadena. Value permet obviar el nom de l’atribut.

Implementació de la classe LoadJsonFilePostProcessor

LoadJsonFilePostProcessor.java
package utilites;
public class LoadJsonFilePostProcessor implements TestInstancePostProcessor {
        private final ResourceLoader resourceLoader = new DefaultResourceLoader();
        private final ObjectMapper objectMapper = new ObjectMapper();
    @Override
    public void postProcessTestInstance(final Object testInstance, final ExtensionContext context) throws Exception {
        final Class<?> testClass = testInstance.getClass();
        for (final Field field : testClass.getDeclaredFields()) {
            final LoadJsonFile annotation = field.getAnnotation(LoadJsonFile.class);
            if (annotation != null) {
                field.setAccessible(true);
                final Object value = loadJsonFile(annotation.value(), field.getType());
                field.set(testInstance, value);
            }
        }
    }

    private <T> T loadJsonFile(final String filePath, final Class<T> type) {
        final Resource resource = resourceLoader.getResource(filePath);
        try (final InputStream inputStream = resource.getInputStream()) {
            return objectMapper.readValue(filePath, type);
        } catch (Exception e) {
            throw new RuntimeException("Failed to load JSON file: " + filePath, e);
        }
    }
}

Explicació de la classe

  • TestInstancePostProcessor: Interfície de JUnit 5 que permet modificar la instància de prova abans que s’executi.
  • ResourceLoader: Utilitzat per a carregar recursos (fitxers) des del classpath. Això acobla la solució a Spring.
  • ObjectMapper: Classe de Jackson utilitzada per a deserialitzar el JSON i passar-lo a Java.
  • postProcessTestInstance: Recorre els camps de la classe de prova i busca l’anotació @LoadJsonFile
  • loadJsonFile: Carrega el fitxer JSON des de la ruta proporcionada i el converteix en un objecte del tipus especificat.

Pots trobar més informació sobre TestInstancePostProcessor a la documentació oficial de JUnit 5.

Exemple d’ús

ExampleTest.java

@ExtendWith(MockitoExtension.class, LoadJsonFilePostProcessor.class)
public class ExampleTest {
    @LoadJsonFile("sample-data.json")
    private SampleData sampleData;

    @Test
    public void testLoadJsonFile() {
        assertNotNull(sampleData);
        assertEquals("John Doe", sampleData.getName());
        assertEquals(30, sampleData.getAge());
    }
}
  • Java
  • Testing
Compartir: