Come la maggior parte delle persone che hanno trovato questo thread, stavo scrivendo alcuni test unitari e dovevo modificare le variabili di ambiente per impostare le condizioni corrette per l'esecuzione del test. Tuttavia, ho scoperto che le risposte più votate avevano alcuni problemi e / o erano molto criptiche o eccessivamente complicate. Speriamo che questo possa aiutare gli altri a risolvere la soluzione più rapidamente.
Prima di tutto, ho finalmente trovato la soluzione di @Hubert Grzeskowiak per essere la più semplice e ha funzionato per me. Vorrei essere venuto prima a quello. Si basa sulla risposta di @Edward Campbell, ma senza complicare la ricerca in loop.
Tuttavia, ho iniziato con la soluzione di @ pushy, che ha ottenuto il maggior numero di voti. È una combinazione di @anonymous e @Edward Campbell. @pushy afferma che entrambi gli approcci sono necessari per coprire ambienti Linux e Windows. Sono in esecuzione su OS X e trovo che entrambi funzionano (una volta risolto un problema con l'approccio @anonymous). Come altri hanno notato, questa soluzione funziona la maggior parte delle volte, ma non tutto.
Penso che la fonte della maggior parte della confusione derivi dalla soluzione di @ anonymous operante nel campo "theEnvironment". Guardando la definizione della struttura ProcessEnvironment , 'theEnvironment' non è una mappa <String, String> ma piuttosto una mappa <Variabile, Valore>. L'eliminazione della mappa funziona correttamente, ma l'operazione putAll ricostruisce la mappa una <stringa, stringa>, che potenzialmente causa problemi quando le operazioni successive operano sulla struttura dei dati utilizzando l'API normale che prevede la mappa <variabile, valore>. Inoltre, l'accesso / rimozione di singoli elementi è un problema. La soluzione è accedere indirettamente all '"Ambiente" tramite "Ambiente immodificabile". Ma poiché questo è un tipo UnmodifiableMapl'accesso deve essere effettuato tramite la variabile privata 'm' del tipo UnmodifiableMap. Vedi getModifiableEnvironmentMap2 nel codice seguente.
Nel mio caso ho dovuto rimuovere alcune delle variabili d'ambiente per il mio test (le altre dovrebbero essere invariate). Quindi ho voluto ripristinare le variabili di ambiente al loro stato precedente dopo il test. Le routine sottostanti lo rendono semplice. Ho testato entrambe le versioni di getModifiableEnvironmentMap su OS X ed entrambe funzionano in modo equivalente. Sebbene basato sui commenti in questo thread, uno potrebbe essere una scelta migliore dell'altro a seconda dell'ambiente.
Nota: non ho incluso l'accesso a "theCaseInsensitiveEnvironmentField" poiché sembra essere specifico di Windows e non ho avuto modo di testarlo, ma aggiungerlo dovrebbe essere semplice.
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);
}