Struct mimicry::Shared

source ·
pub struct Shared<T> { /* private fields */ }
Available on crate feature shared only.
Expand description

Wrapper around Mock state that provides cross-thread synchronization.

This type rarely needs to be used directly; #[derive(Mock)] macro with a #[mock(shared)] attribute on the container will set it up automatically.

Unlike ThreadLocal wrapper, this one shares the state across threads, with state synchronization via reentrant mutexes (to allow for recursive calls). Setting the state is synchronized via a mutex as well: while one test thread has a MockGuard, other tests attempting to set the state will block.

Pitfalls

Tests that do not set the mock state (i.e., ones that want to deal with real implementations) can still observe a mock impl “spilled” from another test. This is most probably not what you want, and there are ways to deal with this issue:

  • Run tests one at a time via cargo test -j 1.
  • Call Mock::lock() at the beginning of the relevant tests.

Examples

use mimicry::{mock, CheckRealCall, Mock};

#[derive(Debug, Default, Mock)]
#[mock(shared)]
// ^ use the `Shared` wrapper instead of the default thread-local one
struct MockState {
    counter: AtomicU32,
}

impl MockState {
    fn answer(&self) -> u32 {
        self.counter.fetch_add(1, Ordering::Relaxed)
    }
}

// Mocked function.
#[mock(using = "MockState")]
fn answer() -> u32 { 42 }

#[test]
fn some_test() {
    // Sets the mock state until `mock_guard` is dropped.
    let mock_guard = MockState::default().set_as_mock();
    // Call mocked functions (maybe, indirectly). Calls may originate
    // from different threads.
    let threads: Vec<_> = (0..5).map(|_| thread::spawn(answer)).collect();
    let answers: HashSet<_> = threads
        .into_iter()
        .map(|handle| handle.join().unwrap())
        .collect();
    assert_eq!(answers, HashSet::from_iter(0..5));

    let state = mock_guard.into_inner();
    // Can check the state here...
    assert_eq!(state.counter.into_inner(), 5);
}

Trait Implementations

Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.