Skip to main content
tokio-test provides testing utilities for Tokio and futures-based code. It includes mock I/O types, task harnesses for polling futures, and stream testing utilities.

Installation

Add tokio-test to your dev dependencies:
Cargo.toml
tokio-test is typically used only in dev-dependencies since it’s designed for testing.

Core Features

Mock I/O

Scriptable AsyncRead/AsyncWrite implementations

Task Harness

Poll futures without runtime boilerplate

Stream Testing

Mock streams for testing stream consumers

Mock I/O

The io module provides mock types that follow a predefined script of read and write operations. This is perfect for testing networking code without real network I/O.

Basic Mock Builder

If your code attempts operations not in the script, the mock will panic. This helps catch unexpected I/O patterns.

Simulating Read Errors

Simulating Write Errors

Adding Delays

Simulate network latency:

Testing Protocol Implementation

Task Harness

The task module provides utilities for polling futures without needing the full runtime setup.

Basic Task Spawning

Notice this is a regular #[test], not #[tokio::test]. The task harness doesn’t require the Tokio runtime.

Testing Pending Futures

Tracking Wakeups

The task harness tracks how many times the future has been woken:

Testing Streams

The task harness also works with streams:

Testing Within Tokio Context

Some futures require the Tokio runtime context. You can still use the task harness inside #[tokio::test]:

Stream Mock

The stream_mock module provides a way to test stream consumers by controlling what values are yielded.

Basic Stream Mock

block_on Helper

For simple cases, tokio_test::block_on provides a quick way to run async code:
This creates a new current-thread runtime for each call. For more control, use #[tokio::test] instead.

Testing Patterns

Testing Error Handling

Testing Request-Response Patterns

Testing Timeout Behavior

Assertions and Macros

Custom Assertion Helpers

Best Practices

Mock I/O eliminates network unpredictability and makes tests faster and more reliable.
Use read_error and write_error to verify your code handles failures gracefully.
Complex I/O scripts are hard to maintain. Consider breaking tests into smaller units.
Use is_woken() to ensure futures don’t wake unnecessarily, which can indicate performance issues.

Comparison with Alternatives

Use Case
  • Task harness can be used with or without the runtime, but some futures require runtime context.

Resources

API Documentation

Complete API reference on docs.rs

Testing Guide

Comprehensive testing guide on Tokio website

GitHub Repository

View source code and examples

tokio::test macro

Learn about the #[tokio::test] macro