Giống như hầu hết những người đã tìm thấy chủ đề này, tôi đã viết một số bài kiểm tra đơn vị và cần sửa đổi các biến môi trường để đặt các điều kiện chính xác cho bài kiểm tra chạy. Tuy nhiên, tôi thấy các câu trả lời được đánh giá cao nhất có một số vấn đề và / hoặc rất khó hiểu hoặc quá phức tạp. Hy vọng rằng điều này sẽ giúp những người khác sắp xếp giải pháp nhanh hơn.
Trước hết, cuối cùng tôi đã tìm thấy giải pháp của @Hubert Grzeskowiak là đơn giản nhất và nó hiệu quả với tôi. Tôi ước tôi sẽ đến cái đó trước. Nó dựa trên câu trả lời của @Edward Campbell, nhưng không phức tạp cho tìm kiếm vòng lặp.
Tuy nhiên, tôi đã bắt đầu với giải pháp @ Pushy, giải pháp được nhiều người ủng hộ nhất. Nó là sự kết hợp của @anonymous và @Edward Campbell's. @pushy tuyên bố cả hai cách tiếp cận đều cần thiết để bao quát cả môi trường Linux và Windows. Tôi đang chạy trên OS X và thấy rằng cả hai đều hoạt động (một khi vấn đề với cách tiếp cận @anonymous được khắc phục). Như những người khác đã lưu ý, giải pháp này hoạt động hầu hết thời gian, nhưng không phải tất cả.
Tôi nghĩ rằng nguồn gốc của hầu hết sự nhầm lẫn đến từ giải pháp của @ nặc danh hoạt động trên trường 'môi trường'. Nhìn vào định nghĩa của cấu trúc ProcessEn Môi trường, 'Môi trường' không phải là Bản đồ <Chuỗi, Chuỗi> mà là Bản đồ <Biến, Giá trị>. Xóa bản đồ hoạt động tốt, nhưng thao tác putAll sẽ xây dựng lại bản đồ <Chuỗi, Chuỗi>, có khả năng gây ra sự cố khi các hoạt động tiếp theo hoạt động trên cấu trúc dữ liệu bằng API thông thường mong đợi Bản đồ <Biến, Giá trị>. Ngoài ra, truy cập / loại bỏ các yếu tố cá nhân là một vấn đề. Giải pháp là truy cập gián tiếp vào 'môi trường' thông qua 'theUnmodifiableEn Môi trường'. Nhưng vì đây là loại UnmodifiableMapviệc truy cập phải được thực hiện thông qua biến riêng 'm' của loại UnmodifiableMap. Xem getModifiableEn MôiMap2 trong mã bên dưới.
Trong trường hợp của tôi, tôi cần phải loại bỏ một số biến môi trường cho thử nghiệm của mình (những biến khác không thay đổi). Sau đó, tôi muốn khôi phục các biến môi trường về trạng thái trước của chúng sau khi thử nghiệm. Các thói quen dưới đây làm cho thẳng về phía trước để làm. Tôi đã thử nghiệm cả hai phiên bản getModifiableEn Môi trường trên OS X và cả hai đều hoạt động tương đương. Mặc dù dựa trên các nhận xét trong chủ đề này, một người có thể là một lựa chọn tốt hơn so với người khác tùy thuộc vào môi trường.
Lưu ý: Tôi không bao gồm quyền truy cập vào 'theCaseInsensitiveEn MôiField' vì đó có vẻ là đặc thù của Windows và tôi không có cách nào để kiểm tra nó, nhưng việc thêm nó sẽ rất đơn giản.
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);
}