Comme la plupart des gens qui ont trouvé ce fil, j'écrivais des tests unitaires et je devais modifier les variables d'environnement pour définir les conditions correctes pour l'exécution du test. Cependant, j'ai trouvé que les réponses les plus votées avaient des problèmes et / ou étaient très cryptiques ou trop compliquées. J'espère que cela aidera les autres à trier la solution plus rapidement.
Tout d'abord, j'ai finalement trouvé la solution de @Hubert Grzeskowiak la plus simple et cela a fonctionné pour moi. J'aurais aimé y arriver en premier. Il est basé sur la réponse de @Edward Campbell, mais sans compliquer la recherche de boucle.
Cependant, j'ai commencé avec la solution de @ pushy, qui a obtenu le plus de votes positifs. Il s'agit d'un combo de @anonymous et @Edward Campbell's. @pushy affirme que les deux approches sont nécessaires pour couvrir les environnements Linux et Windows. Je suis sous OS X et je trouve que les deux fonctionnent (une fois qu'un problème avec l'approche @anonymous est résolu). Comme d'autres l'ont noté, cette solution fonctionne la plupart du temps, mais pas tous.
Je pense que la source de la plupart des confusions vient de la solution de @ anonymous opérant sur le champ 'theEnvironment'. En regardant la définition de la structure ProcessEnvironment , 'theEnvironment' n'est pas une Map <String, String> mais plutôt une Map <Variable, Value>. L'effacement de la carte fonctionne correctement, mais l'opération putAll reconstruit la carte en Map <String, String>, ce qui peut potentiellement poser des problèmes lorsque des opérations ultérieures opèrent sur la structure de données à l'aide de l'API normale qui attend Map <Variable, Value>. De plus, l'accès / la suppression d'éléments individuels est un problème. La solution consiste à accéder indirectement à «l'environnement» via «l'environnement non modifiable». Mais puisque c'est un type UnmodifiableMapl'accès doit se faire via la variable privée 'm' de type UnmodifiableMap. Voir getModifiableEnvironmentMap2 dans le code ci-dessous.
Dans mon cas, j'ai dû supprimer certaines des variables d'environnement pour mon test (les autres doivent rester inchangées). Ensuite, j'ai voulu restaurer les variables d'environnement à leur état antérieur après le test. Les routines ci-dessous rendent cela simple. J'ai testé les deux versions de getModifiableEnvironmentMap sur OS X, et les deux fonctionnent de manière équivalente. Bien que basé sur les commentaires de ce fil, l'un peut être un meilleur choix que l'autre en fonction de l'environnement.
Remarque: Je n'ai pas inclus l'accès au '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);
}