#async #mocking #tokio #run-time #compatible #clock

async-time-mock-tokio

Mockable time for use in async runtimes (tokio compatibility)

3 unstable releases

0.1.1 Jan 22, 2024
0.1.0 Feb 19, 2023
0.0.1 Jan 11, 2023

#440 in Testing

Download history 20/week @ 2024-07-20 30/week @ 2024-07-27 17/week @ 2024-08-03 9/week @ 2024-08-10 25/week @ 2024-08-17 1/week @ 2024-08-24 7/week @ 2024-08-31 41/week @ 2024-09-07 36/week @ 2024-09-14 13/week @ 2024-09-21 1/week @ 2024-09-28 9/week @ 2024-10-05 10/week @ 2024-10-12 1/week @ 2024-10-19 113/week @ 2024-11-02

125 downloads per month

MIT license

19KB
438 lines

async-time-mock-tokio

Asynchronous time mocking with a tokio compatible API based on async-time-mock-core, inspired by the approach described in Mocking Time In Async Rust.

NOTE: This library is still in it's infancy, the API is still likely to change (read: improve). Please leave your feedback and suggestions on GitHub.

Cargo features

  • mock: Enable the mock clock. If you only enable this in tests, this library turns into a thin wrapper around tokio's time functions.

Example

use async_time_mock_tokio::MockableClock;
use std::{
	sync::atomic::{AtomicBool, Ordering},
	time::Duration,
};

static HAS_SLEPT: AtomicBool = AtomicBool::new(false);

async fn sleep(clock: MockableClock) {
	// Sleep is either mocked or a real tokio::sleep, depending on which variant of `MockableClock` you pass in.
	let _guard = clock.sleep(Duration::from_secs(3600)).await;
	// Dropping this guard signifies that all the effects of the timer have finished.
	// This allows test code to wait until the condition to assert for has happened.

	println!("Slept for an hour");
	HAS_SLEPT.store(true, Ordering::SeqCst);
}

#[tokio::main]
async fn main() {
	let (clock, controller) = MockableClock::mock(); // In production, you can use MockableClock::Real instead

	tokio::spawn(sleep(clock));

	controller.advance_time(Duration::from_secs(600)).await;
	assert!(!HAS_SLEPT.load(Ordering::SeqCst), "Timer won't trigger after just 10 minutes.");

	// advance_time will first trigger the sleep in the task above and then wait until the `_guard` was dropped.
	// This ensures that the task had enough time to actually set `HAS_SLEPT` to `true`.
	controller.advance_time(Duration::from_secs(3000)).await;
	assert!(HAS_SLEPT.load(Ordering::SeqCst), "Timer has triggered after 1 hour.")
}

Dependencies

~2.3–8MB
~64K SLoC