
Tests de configuration avec `@TestPropertySource`
Apprenez à contrôler et surcharger les propriétés de configuration de vos applications Spring Boot pendant les tests grâce à l'annotation @TestPropertySource.
Pourquoi tester la configuration ?
La configuration est un pilier des applications Spring Boot. Elle détermine le comportement de nombreux aspects, de la connexion à la base de données à l'activation de fonctionnalités spécifiques, en passant par l'intégration avec des services externes. Il est donc essentiel de pouvoir tester que l'application se comporte correctement sous différentes configurations, ou de pouvoir surcharger certaines propriétés spécifiquement pour l'environnement de test.
Par exemple, lors des tests d'intégration, vous ne voulez probablement pas vous connecter à la base de données de production. Vous pourriez vouloir utiliser une base de données en mémoire (comme H2) ou une instance de base de données éphémère (via Testcontainers). De même, vous pourriez vouloir désactiver l'envoi d'e-mails ou l'appel à des API externes coûteuses pendant les tests.
Spring Boot offre plusieurs mécanismes pour gérer la configuration, et `@TestPropertySource` est une annotation spécifiquement conçue pour manipuler les propriétés de l'environnement Spring (`Environment`) dans le contexte d'un test, de manière déclarative et flexible.
Présentation de `@TestPropertySource`
L'annotation `@TestPropertySource`, fournie par le module `spring-test`, permet d'ajouter ou de remplacer des propriétés dans l'`Environment` de Spring pour un test donné. Ces propriétés peuvent provenir de fichiers spécifiques ou être définies directement dans l'annotation.
Elle s'applique au niveau de la classe de test et influence le contexte d'application chargé pour ce test. Les propriétés définies via `@TestPropertySource` ont une priorité très élevée, surpassant celles définies dans les fichiers `application.properties` ou `application.yml` standards, ainsi que les propriétés système ou les variables d'environnement (sauf celles définies directement au lancement du test par le build tool ou l'IDE).
Cela permet de configurer précisément l'environnement d'exécution pour le test, assurant que les beans (`@Component`, `@Service`, `@ConfigurationProperties`, etc.) sont initialisés avec les valeurs de configuration souhaitées pour le scénario de test.
Utilisation de `@TestPropertySource`
Il existe deux manières principales d'utiliser `@TestPropertySource` : en définissant des propriétés directement (inline) ou en spécifiant l'emplacement de fichiers de propriétés.
1. Propriétés Inline (`properties` attribute): Vous pouvez fournir des paires clé=valeur directement dans l'annotation. C'est pratique pour surcharger un petit nombre de propriétés.
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest
@TestPropertySource(properties = {
"app.feature.enabled=false", // Surcharge une propriété existante ou en ajoute une nouvelle
"external.service.url=http://localhost:9999/mock-api" // Définit une URL pour un mock
})
class InlinePropertyTest {
@Value("${app.feature.enabled}")
private boolean featureEnabled;
@Value("${external.service.url}")
private String serviceUrl;
@Test
void propertiesShouldBeOverridden() {
assertThat(featureEnabled).isFalse();
assertThat(serviceUrl).isEqualTo("http://localhost:9999/mock-api");
}
}
2. Fichiers de Propriétés (`locations` attribute): Pour des configurations de test plus complexes, il est préférable de les externaliser dans des fichiers. `@TestPropertySource` peut charger des fichiers `.properties` ou `.yml`/`.yaml` depuis le classpath.
Créez un fichier `src/test/resources/test-config.properties` :
# src/test/resources/test-config.properties
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.username=sa
spring.datasource.password=
logging.level.com.example=DEBUG
Utilisez-le dans votre test :
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.env.Environment;
import org.springframework.test.context.TestPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest
@TestPropertySource(locations = "classpath:/test-config.properties")
class LocationPropertyTest {
@Autowired
private Environment environment;
@Test
void propertiesShouldBeLoadedFromFile() {
assertThat(environment.getProperty("spring.datasource.url")).isEqualTo("jdbc:h2:mem:testdb");
assertThat(environment.getProperty("logging.level.com.example")).isEqualTo("DEBUG");
}
}
Vous pouvez combiner `properties` et `locations`. En cas de conflit, les propriétés définies inline dans `properties` ont priorité sur celles des fichiers spécifiés dans `locations`.
Contrôle de l'héritage des propriétés
Par défaut (`inheritProperties = true`), les propriétés définies via `@TestPropertySource` s'ajoutent ou surchargent celles de l'environnement standard (par exemple, `application.properties`). Si vous souhaitez que *seules* les propriétés définies dans `@TestPropertySource` soient prises en compte (ignorant complètement `application.properties`, les variables d'environnement, etc.), vous pouvez définir `inheritProperties = false`.
@SpringBootTest
@TestPropertySource(locations = "classpath:/minimal-test-config.properties", inheritProperties = false)
class InheritFalsePropertyTest {
// ... le test ne verra que les propriétés de minimal-test-config.properties
}
Utilisez `inheritProperties = false` avec prudence, car cela peut désactiver des configurations essentielles de Spring Boot si elles ne sont pas redéfinies dans vos propriétés de test.
L'attribut `inheritLocations` (par défaut `true`) contrôle si les `@TestPropertySource` définis dans les superclasses ou les classes englobantes sont également pris en compte.
Cas d'usage et combinaison avec `@ActiveProfiles`
`@TestPropertySource` est extrêmement utile pour :
- Configurer une base de données H2 ou Testcontainers pour les tests d'intégration.
- Désactiver des tâches planifiées (`spring.task.scheduling.enabled=false`).
- Fournir des URLs ou des clés API pour des services mockés.
- Tester le comportement d'un bean `@ConfigurationProperties` avec des valeurs spécifiques.
- Activer ou désactiver des fonctionnalités via des feature flags pour différents scénarios de test.
Vous pouvez combiner `@TestPropertySource` avec `@ActiveProfiles` pour simuler des environnements encore plus spécifiques. Par exemple, activer un profil "test" et surcharger une propriété particulière de ce profil :
import org.springframework.test.context.ActiveProfiles;
@SpringBootTest
@ActiveProfiles("test") // Charge application-test.properties
@TestPropertySource(properties = { "specific.test.setting=overriddenValue" }) // Surcharge une valeur spécifique
class ProfileAndPropertyTest {
// ...
}
Rappelez-vous que les propriétés définies dans `@TestPropertySource` (inline ou via `locations`) auront généralement priorité sur celles des fichiers `application-{profile}.properties` chargés par `@ActiveProfiles`.
En maîtrisant `@TestPropertySource`, vous gagnez un contrôle fin sur l'environnement de configuration de vos tests Spring Boot, ce qui est essentiel pour écrire des tests robustes, isolés et ciblés.