Wie die meisten Leute, die diesen Thread gefunden haben, habe ich einige Unit-Tests geschrieben und musste die Umgebungsvariablen ändern, um die richtigen Bedingungen für die Ausführung des Tests festzulegen. Ich stellte jedoch fest, dass die am meisten hochgestuften Antworten einige Probleme aufwiesen und/oder sehr kryptisch oder übermäßig kompliziert waren. Hoffentlich hilft dies anderen, die Lösung schneller zu finden.
Zunächst einmal habe ich die Lösung von @Hubert Grzeskowiak als die einfachste gefunden, und sie hat bei mir funktioniert. Ich wünschte, ich wäre zuerst auf diese Lösung gekommen. Sie basiert auf der Antwort von @Edward Campbell, aber ohne die komplizierte for-Schleifensuche.
Ich habe jedoch mit der Lösung von @pushy begonnen, die die meisten Bewertungen erhalten hat. Sie ist eine Kombination aus der von @anonymous und @Edward Campbell. @pushy behauptet, dass beide Ansätze erforderlich sind, um sowohl Linux- als auch Windows-Umgebungen abzudecken. Ich arbeite unter OS X und finde, dass beide funktionieren (sobald ein Problem mit @anonymous Ansatz behoben ist). Wie andere festgestellt haben, funktioniert diese Lösung meistens, aber nicht immer.
Ich denke, der Grund für die meisten Verwirrungen liegt in der Lösung von @anonymous, die mit dem Feld "theEnvironment" arbeitet. Wenn man sich die Definition des Feldes ProzessUmgebung Struktur ist "theEnvironment" keine Map< String, String >, sondern eine Map< Variable, Value >. Das Löschen der Map funktioniert gut, aber die PutAll-Operation baut die Map als Map< String, String > neu auf, was zu Problemen führen kann, wenn nachfolgende Operationen die Datenstruktur mit der normalen API bearbeiten, die Map< Variable, Value > erwartet. Auch der Zugriff auf einzelne Elemente und deren Entfernung ist ein Problem. Die Lösung besteht darin, auf "theEnvironment" indirekt über "theUnmodifiableEnvironment" zuzugreifen. Da dies aber ein Typ ist UnveränderbarMap der Zugriff muss über die private Variable 'm' vom Typ UnmodifiableMap erfolgen. Siehe getModifiableEnvironmentMap2 im nachfolgenden Code.
In meinem Fall musste ich einige der Umgebungsvariablen für meinen Test entfernen (die anderen sollten unverändert bleiben). Dann wollte ich die Umgebungsvariablen nach dem Test wieder in ihren vorherigen Zustand zurückversetzen. Mit den nachstehenden Routinen ist das ganz einfach möglich. Ich habe beide Versionen von getModifiableEnvironmentMap unter OS X getestet, und beide funktionieren gleichwertig. Basierend auf den Kommentaren in diesem Thread könnte die eine Version je nach Umgebung besser geeignet sein als die andere.
Hinweis: Ich habe den Zugriff auf das "theCaseInsensitiveEnvironmentField" nicht mit einbezogen, da es Windows-spezifisch zu sein scheint und ich keine Möglichkeit hatte, es zu testen, aber das Hinzufügen sollte einfach sein.
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);
}