0 day streak
rust / expert
Snippet

Isolating Side Effects in Tests Using Thread-Local Mocking

When writing unit tests in Rust, tests run concurrently by default. To safely mock global functions or FFI state without race conditions, we can use `thread_local!` state. This keeps mocks isolated strictly to the thread executing the specific test case.

snippet.rs
rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
use std::cell::RefCell;
thread_local! {
static MOCK_DB_RESPONSE: RefCell<Option<Result<String, &'static str>>> = const { RefCell::new(None) };
}
fn fetch_data_from_db() -> Result<String, &'static str> {
MOCK_DB_RESPONSE.with(|mock| {
if let Some(ref response) = *mock.borrow() {
response.clone()
} else {
Ok("real_production_data".to_string())
}
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_database_error_handling() {
MOCK_DB_RESPONSE.with(|mock| {
*mock.borrow_mut() = Some(Err("Timeout"));
});
assert_eq!(fetch_data_from_db(), Err("Timeout"));
MOCK_DB_RESPONSE.with(|mock| *mock.borrow_mut() = None);
}
}
Breakdown
1
static MOCK_DB_RESPONSE: RefCell<Option<Result<...>>> = ...
Declares a thread-local static variable containing a RefCell to store the mock outcome.
2
MOCK_DB_RESPONSE.with(|mock| {
Accesses the thread-bound mock container using closure-based scoping.
3
*mock.borrow_mut() = Some(Err("Timeout"));
Configures the failure state on the current test thread without affecting parallel tests.