env_test_util/
lib.rs

1/// Temporary environment variable manager
2///
3/// When initialising the variable manager with `new`, the actual content will be removed and stored
4/// in `initial_value`. You can then set a temporary value using the method `with`. The environment
5/// variable will then be reset to it's initial value when it will be dropped.
6///
7/// # Examples
8///
9/// ```
10/// use env_test_util::TempEnvVar;
11///
12/// std::env::set_var("MY_VARIABLE", "ORIGINAL"); // set the variable to "ORIGINAL"
13/// let variable = TempEnvVar::new("MY_VARIABLE"); // read the variable and stores it
14/// assert_eq!(std::env::var("MY_VARIABLE").ok(), None);
15/// let variable = variable.with("NEW_CONTENT"); // set the environment variable with a new content
16/// assert_eq!(std::env::var("MY_VARIABLE").ok(), Some("NEW_CONTENT".into()));
17/// drop(variable);
18/// assert_eq!(std::env::var("MY_VARIABLE").ok(), Some("ORIGINAL".into()));
19/// ```
20///
21/// Don't forget to assign the variable in your tests, otherwise the `drop` function will be called right away
22///
23/// ```
24/// use env_test_util::TempEnvVar;
25///
26/// std::env::set_var("MY_VARIABLE", "ORIGINAL"); // set the variable to "ORIGINAL"
27/// TempEnvVar::new("MY_VARIABLE").with("SOMETHING_ELSE"); // read the variable and stores it
28/// assert_eq!(std::env::var("MY_VARIABLE").ok(), Some("ORIGINAL".into()));
29/// let _variable = TempEnvVar::new("MY_VARIABLE").with("SOMETHING_ELSE"); // Instead, store it in a variable
30/// assert_eq!(std::env::var("MY_VARIABLE").ok(), Some("SOMETHING_ELSE".into()));
31/// ```
32pub struct TempEnvVar {
33    /// name of the environment variable
34    pub key: String,
35    /// initial value of the environment variable
36    pub initial_value: Option<String>,
37}
38
39impl TempEnvVar {
40    /// creates a new temporary environment variable manager
41    pub fn new(key: &str) -> Self {
42        let initial_value = std::env::var(key).ok();
43        std::env::remove_var(key);
44        Self {
45            key: key.into(),
46            initial_value,
47        }
48    }
49
50    /// set the environment with a new temporary value
51    pub fn with(self, value: &str) -> Self {
52        std::env::set_var(self.key.as_str(), value);
53        self
54    }
55}
56
57impl Drop for TempEnvVar {
58    fn drop(&mut self) {
59        match self.initial_value.as_ref() {
60            Some(value) => std::env::set_var(self.key.as_str(), value),
61            None => std::env::remove_var(self.key.as_str()),
62        }
63    }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn with_non_existing_variable() {
72        let name = "MISSINGVAR";
73        std::env::remove_var(name);
74        let variable = TempEnvVar::new(name);
75        assert_eq!(variable.initial_value, None);
76        assert_eq!(std::env::var(name).ok(), None);
77        let variable = variable.with("SOMETHING");
78        assert_eq!(variable.initial_value, None);
79        assert_eq!(std::env::var(name).ok(), Some("SOMETHING".into()));
80        drop(variable);
81        assert_eq!(std::env::var(name).ok(), None);
82    }
83
84    #[test]
85    fn with_existing_variable() {
86        let name = "EXISTINGVAR";
87        std::env::set_var(name, "INITIAL");
88        let variable = TempEnvVar::new(name);
89        assert_eq!(variable.initial_value, Some("INITIAL".into()));
90        assert_eq!(std::env::var(name).ok(), None);
91        let variable = variable.with("SOMETHING");
92        assert_eq!(variable.initial_value, Some("INITIAL".into()));
93        assert_eq!(std::env::var(name).ok(), Some("SOMETHING".into()));
94        drop(variable);
95        assert_eq!(std::env::var(name).ok(), Some("INITIAL".into()));
96    }
97}