Comme la plupart des personnes qui ont trouvé ce fil de discussion, j'écrivais des tests unitaires et j'avais besoin de modifier les variables d'environnement afin de définir les conditions correctes pour l'exécution du test. Cependant, j'ai trouvé que les réponses les plus votées présentaient quelques problèmes et/ou étaient très cryptiques ou trop compliquées. J'espère que cela aidera les autres à trouver la solution plus rapidement.
Tout d'abord, j'ai finalement trouvé la solution de @Hubert Grzeskowiak comme étant la plus simple et elle a fonctionné pour moi. J'aurais aimé arriver à cette solution en premier. Elle est basée sur la réponse de @Edward Campbell, mais sans la recherche compliquée de la boucle for.
Cependant, j'ai commencé par la solution de @pushy, qui a obtenu le plus de votes positifs. C'est une combinaison des solutions de @anonymous et de @Edward Campbell. @pushy affirme que les deux approches sont nécessaires pour couvrir les environnements Linux et Windows. Je fonctionne sous OS X et je trouve que les deux fonctionnent (une fois qu'un problème avec l'approche de @anonymous sera résolu). Comme d'autres l'ont noté, cette solution fonctionne la plupart du temps, mais pas toujours.
Je pense que la source de la plupart des confusions vient de la solution de @anonymous qui opère sur le champ 'theEnvironment'. En regardant la définition du champ Environnement du processus l'environnement' n'est pas une Map< String, String > mais plutôt une Map< Variable, Value >. L'effacement de la carte fonctionne bien, mais l'opération putAll reconstruit la carte sous la forme d'une Map< String, String >, ce qui peut poser des problèmes lorsque des opérations ultérieures sont effectuées sur la structure de données à l'aide de l'API normale qui attend une Map< Variable, Value >. De plus, l'accès/la suppression d'éléments individuels pose un problème. La solution consiste à accéder indirectement à 'theEnvironment' par le biais de 'theUnmodifiableEnvironment'. Mais comme il s'agit d'un type UnmodifiableMap l'accès doit se faire par la variable privée 'm' du type UnmodifiableMap. Voir getModifiableEnvironmentMap2 dans le code ci-dessous.
Dans mon cas, j'ai dû supprimer certaines variables d'environnement pour mon test (les autres devraient rester inchangées). Ensuite, je voulais restaurer les variables d'environnement à leur état antérieur après le test. Les routines ci-dessous permettent de le faire facilement. J'ai testé les deux versions de getModifiableEnvironmentMap sous OS X, et les deux fonctionnent de manière équivalente. Cependant, d'après les commentaires de ce fil de discussion, l'une peut être un meilleur choix que l'autre en fonction de l'environnement.
Note : Je n'ai pas inclus l'accès au champ 'theCaseInsensitiveEnvironmentField' car cela semble être spécifique à Windows et je n'avais aucun moyen de le tester, mais l'ajouter devrait être simple.
private Map<String, String> getModifiableEnvironmentMap() {
try {
Map<String,String> unmodifiableEnv = System.getenv();
Class<?> cl = unmodifiableEnv.getClass();
Field field = cl.getDeclaredField("m");
field.setAccessible(true);
Map<String,String> modifiableEnv = (Map<String,String>) field.get(unmodifiableEnv);
return modifiableEnv;
} catch(Exception e) {
throw new RuntimeException("Unable to access writable environment variable map.");
}
}
private Map<String, String> getModifiableEnvironmentMap2() {
try {
Class<?> processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
Field theUnmodifiableEnvironmentField = processEnvironmentClass.getDeclaredField("theUnmodifiableEnvironment");
theUnmodifiableEnvironmentField.setAccessible(true);
Map<String,String> theUnmodifiableEnvironment = (Map<String,String>)theUnmodifiableEnvironmentField.get(null);
Class<?> theUnmodifiableEnvironmentClass = theUnmodifiableEnvironment.getClass();
Field theModifiableEnvField = theUnmodifiableEnvironmentClass.getDeclaredField("m");
theModifiableEnvField.setAccessible(true);
Map<String,String> modifiableEnv = (Map<String,String>) theModifiableEnvField.get(theUnmodifiableEnvironment);
return modifiableEnv;
} catch(Exception e) {
throw new RuntimeException("Unable to access writable environment variable map.");
}
}
private Map<String, String> clearEnvironmentVars(String[] keys) {
Map<String,String> modifiableEnv = getModifiableEnvironmentMap();
HashMap<String, String> savedVals = new HashMap<String, String>();
for(String k : keys) {
String val = modifiableEnv.remove(k);
if (val != null) { savedVals.put(k, val); }
}
return savedVals;
}
private void setEnvironmentVars(Map<String, String> varMap) {
getModifiableEnvironmentMap().putAll(varMap);
}
@Test
public void myTest() {
String[] keys = { "key1", "key2", "key3" };
Map<String, String> savedVars = clearEnvironmentVars(keys);
// do test
setEnvironmentVars(savedVars);
}
1 votes
System.getEnv() est destiné à être universel, certains environnements n'ont même pas de variables d'environnement.
17 votes
Pour tous ceux qui en ont eu besoin dans le cadre de tests unitaires : stackoverflow.com/questions/8168884/
1 votes
Pour Scala, utilisez ceci : gist.github.com/vpatryshev/b1bbd15e2b759c157b58b68c58891ff4