Wie die meisten Leute, die diesen Thread gefunden haben, habe ich einige Komponententests geschrieben und musste die Umgebungsvariablen ändern, um die richtigen Bedingungen für die Ausführung des Tests festzulegen. Ich fand jedoch, dass die am besten bewerteten Antworten einige Probleme hatten und / oder sehr kryptisch oder übermäßig kompliziert waren. Hoffentlich hilft dies anderen, die Lösung schneller zu finden.
Als erstes fand ich die Lösung von @Hubert Grzeskowiak am einfachsten und sie funktionierte für mich. Ich wünschte, ich wäre zuerst dazu gekommen. Es basiert auf der Antwort von @Edward Campbell, ohne jedoch die Suche nach Schleifen zu erschweren.
Ich habe jedoch mit der Lösung von @ pushy begonnen, die die meisten positiven Stimmen erhielt. Es ist eine Kombination aus @anonymous und @Edward Campbell's. @pushy behauptet, dass beide Ansätze erforderlich sind, um sowohl Linux- als auch Windows-Umgebungen abzudecken. Ich laufe unter OS X und stelle fest, dass beide funktionieren (sobald ein Problem mit dem @ anonymous-Ansatz behoben ist). Wie andere angemerkt haben, funktioniert diese Lösung die meiste Zeit, aber nicht alle.
Ich denke, die Ursache für den größten Teil der Verwirrung liegt in der Lösung von @onymous, die im Feld "theEnvironment" ausgeführt wird. Bei der Definition der ProcessEnvironment Struktur ist 'theEnvironment' keine Map <String, String>, sondern eine Map <Variable, Value>. Das Löschen der Map funktioniert einwandfrei, aber die putAll-Operation erstellt die Map neu als Map <String, String>, was möglicherweise zu Problemen führt, wenn nachfolgende Operationen die Datenstruktur mit der normalen API bearbeiten, die Map <Variable, Wert> erwartet. Auch der Zugriff auf / das Entfernen einzelner Elemente ist ein Problem. Die Lösung besteht darin, indirekt über 'die nicht veränderbare Umgebung' auf 'theEnvironment' zuzugreifen. Da dies aber ein Typ UnmodizableMap ist muss der Zugriff über die private Variable 'm' vom Typ UnmodizableMap erfolgen. Siehe getModutableEnvironmentMap2 im folgenden 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 auf ihren vorherigen Zustand zurücksetzen. Die folgenden Routinen machen dies einfach. Ich habe beide Versionen von getModutableEnvironmentMap unter OS X getestet und beide funktionieren gleichwertig. Obwohl dies auf Kommentaren in diesem Thread basiert, ist je nach Umgebung möglicherweise eine bessere Wahl als die andere.
Hinweis: Ich habe keinen Zugriff auf das 'theCaseInsensitiveEnvironmentField' hinzugefügt, da dies 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);
}