jaemk / cached

Rust cache structures and easy function memoization
MIT License
1.57k stars 95 forks source link

Disable caching for tests? #130

Closed Clete2 closed 2 years ago

Clete2 commented 2 years ago

Is there an easy way to disable caching for testing purposes?

A simple example is below; where I cache a URL. The second test always fails because the result is still cached from the first test. More complex examples also fail due to caching.

use cached::proc_macro::cached;

#[cached]
fn url() -> String {
    std::env::var("hostname").unwrap_or_else(|_| String::from("some.hostname"))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn url_default() {
        std::env::remove_var("hostname");
        assert_eq!(url(), "some.hostname");
    }

    #[test]
    fn url_override() {
        std::env::set_var("hostname", "some.other.hostname");
        assert_eq!(url(), "some.other.hostname");
    }
}
LikeLakers2 commented 2 years ago

You can use #[cfg_attr()] for this purpose. As an example:

#[cfg_attr(
    not(test),
    cached
)]
pub fn load_as_arc(i: i64) -> Arc<i64> {
    Arc::new(i)
}

will only cache the results of the function if you are not compiling something for tests. (If you want more information on #[cfg_attr()], see here).

That said, I wouldn't used cached in the example code you gave, as cached will never be able to see the change in the environment variable. Cached is meant to be used to avoid running a function if you've called it before with the same exact parameters. In this case, because the parameters of the function call to url() never change (as there are none to change), it will always return the same value after the first call.

Clete2 commented 2 years ago

That's exactly what I needed @LikeLakers2; thank you! I agree with the sentiment of not caching it; what I provided was just an example. In reality I'm caching things like AWS SDK clients which are relatively expensive to create.