Como la mayoría de las personas que han encontrado este hilo, estaba escribiendo algunas pruebas unitarias y necesitaba modificar las variables de entorno para establecer las condiciones correctas para que se ejecutara la prueba. Sin embargo, descubrí que las respuestas más votadas tenían algunos problemas y / o eran muy crípticas o demasiado complicadas. Esperemos que esto ayude a otros a resolver la solución más rápidamente.
En primer lugar, finalmente encontré que la solución de @Hubert Grzeskowiak era la más simple y funcionó para mí. Desearía haber venido a eso primero. Se basa en la respuesta de @Edward Campbell, pero sin la complicación de la búsqueda en bucle.
Sin embargo, comencé con la solución de @ pushy, que obtuvo la mayor cantidad de votos. Es una combinación de @anonymous y @Edward Campbell's. @pushy afirma que ambos enfoques son necesarios para cubrir los entornos de Linux y Windows. Estoy ejecutando bajo OS X y encuentro que ambos funcionan (una vez que se soluciona un problema con el enfoque @anonymous). Como otros han señalado, esta solución funciona la mayor parte del tiempo, pero no todo.
Creo que la fuente de la mayor parte de la confusión proviene de la solución de @ anonymous que opera en el campo 'theEnvironment'. Mirando la definición de la estructura ProcessEnvironment , 'theEnvironment' no es un Map <String, String> sino un Map <Variable, Value>. Borrar el mapa funciona bien, pero la operación putAll reconstruye el mapa como Map <String, String>, lo que potencialmente causa problemas cuando las operaciones posteriores operan en la estructura de datos utilizando la API normal que espera Map <Variable, Value>. Además, acceder / eliminar elementos individuales es un problema. La solución es acceder indirectamente a 'theEnvironment' a través de 'theUnmodifiableEnvironment'. Pero como este es un tipo UnmodifiableMapel acceso debe hacerse a través de la variable privada 'm' del tipo UnmodifiableMap. Vea getModifiableEnvironmentMap2 en el código a continuación.
En mi caso, necesitaba eliminar algunas de las variables de entorno para mi prueba (las otras no deberían modificarse). Luego quise restaurar las variables de entorno a su estado anterior después de la prueba. Las rutinas a continuación lo hacen sencillo. Probé ambas versiones de getModifiableEnvironmentMap en OS X, y ambas funcionan de manera equivalente. Aunque basado en los comentarios en este hilo, uno puede ser una mejor opción que el otro dependiendo del entorno.
Nota: No incluí el acceso al 'theCaseInsensitiveEnvironmentField' ya que parece ser específico de Windows y no tenía forma de probarlo, pero agregarlo debería ser sencillo.
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);
}