Seperti kebanyakan orang yang telah menemukan utas ini, saya sedang menulis beberapa unit test dan perlu memodifikasi variabel lingkungan untuk menetapkan kondisi yang benar untuk menjalankan tes. Namun, saya menemukan jawaban yang paling banyak dipilih memiliki beberapa masalah dan / atau sangat samar atau terlalu rumit. Semoga ini akan membantu orang lain untuk memilah solusi lebih cepat.
Pertama, saya akhirnya menemukan solusi @ Hubert Grzeskowiak sebagai solusi paling sederhana dan berhasil bagi saya. Saya berharap saya akan datang ke yang pertama. Ini didasarkan pada jawaban @Edward Campbell, tetapi tanpa menyulitkan untuk pencarian loop.
Namun, saya mulai dengan solusi @ pushy, yang mendapat sebagian besar upvotes. Ini adalah kombinasi dari @anonymous dan @Edward Campbell's. @pushy mengklaim kedua pendekatan diperlukan untuk mencakup lingkungan Linux dan Windows. Saya menjalankan OS X dan menemukan bahwa keduanya berfungsi (sekali masalah dengan pendekatan @anonymous diperbaiki). Seperti yang telah dicatat orang lain, solusi ini bekerja sebagian besar waktu, tetapi tidak semua.
Saya pikir sumber dari sebagian besar kebingungan berasal dari solusi @ anonim yang beroperasi di bidang 'theEnvironment'. Melihat definisi ProcessEnvironment struktur , 'theEnvironment' bukanlah Map <String, String> melainkan Map <Variable, Value>. Mengosongkan peta berfungsi dengan baik, tetapi operasi putAll membangun kembali peta sebuah Peta <String, String>, yang berpotensi menyebabkan masalah ketika operasi selanjutnya beroperasi pada struktur data menggunakan API normal yang mengharapkan Peta <Variable, Value>. Juga, mengakses / menghapus elemen individual adalah masalah. Solusinya adalah mengakses 'theEnvironment' secara tidak langsung melalui 'theUnmnable Ennvironment'. Tapi karena ini adalah tipe UnmodifiableMap , akses harus dilakukan melalui variabel pribadi 'm' dari tipe UnmodifiableMap. Lihat getModifiableEnvironmentMap2 dalam kode di bawah ini.
Dalam kasus saya, saya perlu menghapus beberapa variabel lingkungan untuk pengujian saya (yang lain harus tidak berubah). Kemudian saya ingin mengembalikan variabel lingkungan ke keadaan sebelumnya setelah pengujian. Rutinitas di bawah ini membuatnya mudah untuk dilakukan. Saya menguji kedua versi getModifiableEnvironmentMap pada OS X, dan keduanya bekerja dengan setara. Meskipun berdasarkan komentar di utas ini, yang satu mungkin merupakan pilihan yang lebih baik daripada yang lain tergantung pada lingkungan.
Catatan: Saya tidak memasukkan akses ke 'theCaseInsensitiveEnvironmentField' karena itu sepertinya Windows khusus dan saya tidak punya cara untuk mengujinya, tetapi menambahkan itu harus lurus ke depan.
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);
}