200 votes

Comment tester du code dépendant de variables d'environnement avec JUnit ?

J'ai un morceau de code Java qui utilise une variable d'environnement et le comportement du code dépend de la valeur de cette variable. J'aimerais tester ce code avec différentes valeurs de la variable d'environnement. Comment puis-je faire cela dans JUnit ?

J'ai vu quelques façons de définir des variables d'environnement en Java en général, mais je suis plus intéressé par l'aspect des tests unitaires, surtout si l'on considère que les tests ne devraient pas interférer les uns avec les autres.

254voto

Stefan Birkner Points 3080

La bibliothèque Système Lambda a une méthode withEnvironmentVariable pour définir les variables d'environnement.

import static com.github.stefanbirkner.systemlambda.SystemLambda.*;

public void EnvironmentVariablesTest {
  @Test
  public void setEnvironmentVariable() {
    String value = withEnvironmentVariable("name", "value")
      .execute(() -> System.getenv("name"));
    assertEquals("value", value);
  }
}

Pour Java 5 à 7, la bibliothèque Règles du système possède une règle JUnit appelée EnvironmentVariables .

import org.junit.contrib.java.lang.system.EnvironmentVariables;

public class EnvironmentVariablesTest {
  @Rule
  public final EnvironmentVariables environmentVariables
    = new EnvironmentVariables();

  @Test
  public void setEnvironmentVariable() {
    environmentVariables.set("name", "value");
    assertEquals("value", System.getenv("name"));
  }
}

Révélation complète : je suis l'auteur des deux bibliothèques.

126voto

Matthew Farwell Points 31257

La solution habituelle consiste à créer une classe qui gère l'accès à cette variable environnementale, que vous pouvez ensuite simuler dans votre classe de test.

public class Environment {
    public String getVariable() {
        return System.getenv(); // or whatever
    }
}

public class ServiceTest {
    private static class MockEnvironment {
        public String getVariable() {
           return "foobar";
        }
    }

    @Test public void testService() {
        service.doSomething(new MockEnvironment());
    }
}

La classe testée obtient alors la variable d'environnement en utilisant la classe Environment, et non directement à partir de System.getenv().

47voto

RLD Points 386

Dans une situation similaire où je devais écrire Cas de test qui dépend de Variable d'environnement J'ai essayé ce qui suit :

  1. Je suis allé chercher Règles du système comme suggéré par Stefan Birkner . Son utilisation était simple. Mais très vite, j'ai constaté que son comportement était erratique. Lors d'une exécution, il fonctionne, et lors de l'exécution suivante, il échoue. J'ai fait des recherches et j'ai découvert que les règles de système fonctionnent bien avec JUnit 4 ou une version plus récente. Mais dans mon cas, j'utilisais des Jars qui dépendaient de JUnit 3 . J'ai donc sauté Règles du système . Pour en savoir plus, cliquez ici L'annotation @Rule ne fonctionne pas lors de l'utilisation de TestSuite dans JUnit .
  2. J'ai ensuite essayé de créer Variable d'environnement à travers Constructeur de processus fournie par Java . Ici, le code Java nous permet de créer une variable d'environnement, mais vous devez connaître le code de l'environnement. processus o programme que je n'ai pas. De plus, il crée une variable d'environnement pour le processus enfant, et non pour le processus principal.

J'ai perdu une journée à utiliser les deux approches ci-dessus, mais en vain. Ensuite, j'ai perdu une journée à utiliser les deux approches susmentionnées, mais en vain. Maven est venu à mon secours. Nous pouvons définir Variables d'environnement o Propriétés du système à travers POM Maven ce qui, à mon avis, est la meilleure façon de procéder Tests unitaires pour Maven Le projet est basé sur un système de gestion de l'information et de la communication. Vous trouverez ci-dessous l'entrée que j'ai faite dans POM fichier.

    <build>
      <plugins>
       <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
          <systemPropertyVariables>
              <PropertyName1>PropertyValue1</PropertyName1>                                                          
              <PropertyName2>PropertyValue2</PropertyName2>
          </systemPropertyVariables>
          <environmentVariables>
            <EnvironmentVariable1>EnvironmentVariableValue1</EnvironmentVariable1>
            <EnvironmentVariable2>EnvironmentVariableValue2</EnvironmentVariable2>
          </environmentVariables>
        </configuration>
      </plugin>
    </plugins>
  </build>

Après cette modification, j'ai exécuté Cas de test et soudain, tout a fonctionné comme prévu. Pour l'information du lecteur, j'ai exploré cette approche dans Maven 3.x Je n'ai donc aucune idée de ce qu'il en est. Maven 2.x .

20voto

pgkelley Points 136

Je pense que la façon la plus propre de le faire est d'utiliser Mockito.spy(). C'est un peu plus léger que de créer une classe séparée pour se moquer et la faire circuler.

Déplacez votre recherche de variables d'environnement vers une autre méthode :

@VisibleForTesting
String getEnvironmentVariable(String envVar) {
    return System.getenv(envVar);
}

Maintenant, dans votre test unitaire, faites ceci :

@Test
public void test() {
    ClassToTest classToTest = new ClassToTest();
    ClassToTest classToTestSpy = Mockito.spy(classToTest);
    Mockito.when(classToTestSpy.getEnvironmentVariable("key")).thenReturn("value");
    // Now test the method that uses getEnvironmentVariable
    assertEquals("changedvalue", classToTestSpy.methodToTest());
}

15voto

beatngu13 Points 1877

Pour les utilisateurs de JUnit 4, Système Lambda comme suggéré par Stefan Birkner est très bien adapté.

Si vous utilisez JUnit 5, vous disposez de la fonction JUnit Pionnier pack d'extension. Il comprend @ClearEnvironmentVariable y @SetEnvironmentVariable . De la documents :

En @ClearEnvironmentVariable y @SetEnvironmentVariable peuvent être utilisées pour effacer, respectivement définir les valeurs des variables d'environnement pour l'exécution d'un test. Les deux annotations fonctionnent au niveau de la méthode de test et de la classe, sont répétables et combinables. Après l'exécution de la méthode annotée, les variables mentionnées dans l'annotation retrouveront leur valeur initiale ou seront effacées si elles n'en avaient pas auparavant. Les autres variables d'environnement qui sont modifiées pendant le test sont les suivantes no restauré.

Exemple :

@Test
@ClearEnvironmentVariable(key = "SOME_VARIABLE")
@SetEnvironmentVariable(key = "ANOTHER_VARIABLE", value = "new value")
void test() {
    assertNull(System.getenv("SOME_VARIABLE"));
    assertEquals("new value", System.getenv("ANOTHER_VARIABLE"));
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X