Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Testing in Rust vs Java
Rust 与 Java 的测试方式对照

What you’ll learn: How Rust testing maps to JUnit-style workflows, where parameterized tests fit, and how property testing and mocking compare to the Java ecosystem.
本章将学习: Rust 测试模型如何对应 JUnit 风格工作流、参数化测试放在什么位置,以及性质测试和 mock 手法与 Java 生态如何对应。

Difficulty: 🟡 Intermediate
难度: 🟡 中级

Rust testing feels much closer to library development than to framework-heavy test runners. The defaults are small and built in.
Rust 的测试模型更像贴着库开发本身展开,而不是围绕一个很重的测试框架转。默认能力很小、很直接,而且是内建的。

Unit Tests
单元测试

class CalculatorTest {
    @org.junit.jupiter.api.Test
    void addReturnsSum() {
        assertEquals(5, new Calculator().add(2, 3));
    }
}
#![allow(unused)]
fn main() {
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

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

    #[test]
    fn add_returns_sum() {
        assert_eq!(add(2, 3), 5);
    }
}
}

Test Layout Mapping
测试布局映射

Java habit
Java 习惯
Rust habit
Rust 习惯
src/test/javainline #[cfg(test)] modules or tests/
内联 #[cfg(test)] 模块或 tests/ 目录
JUnit assertionsassert!, assert_eq!, assert_ne!
integration test module
集成测试模块
files in tests/
parameterized tests
参数化测试
rstest crate
property testing libraries
性质测试库
proptest or quickcheck
Mockitomockall or handwritten trait-based fakes
mockall 或手写基于 trait 的 fake

Integration Tests
集成测试

#![allow(unused)]
fn main() {
// tests/api_smoke.rs
use my_crate::parse_user;

#[test]
fn parses_valid_payload() {
    let input = r#"{"id":1,"name":"Ada"}"#;
    assert!(parse_user(input).is_ok());
}
}

Integration tests compile as external consumers of the crate. That makes them a good match for “public API only” expectations.
集成测试会把 crate 当成外部消费者来编译,因此特别适合验证“公共 API 对外是否正常”这件事。

Async Tests
异步测试

#![allow(unused)]
fn main() {
#[tokio::test]
async fn fetch_user_returns_data() {
    let result = fetch_user(42).await;
    assert!(result.is_ok());
}
}

The mental model is straightforward: if production code needs a runtime, async tests need one too.
理解起来很简单:生产代码如果需要运行时,异步测试也需要运行时。

Property Testing
性质测试

Property testing is a strong fit for parsers, codecs, query builders, and data transformations.
解析器、编解码器、查询构造器、数据转换逻辑,这些都特别适合用性质测试补强。

#![allow(unused)]
fn main() {
use proptest::prelude::*;

proptest! {
    #[test]
    fn reversing_twice_returns_original(xs: Vec<i32>) {
        let reversed: Vec<_> = xs.iter().copied().rev().collect();
        let restored: Vec<_> = reversed.iter().copied().rev().collect();
        prop_assert_eq!(xs, restored);
    }
}
}

Advice for Java Teams
给 Java 团队的建议

  • Keep fast unit tests close to the module they validate.
    快速单元测试尽量贴着被测模块写。
  • Add integration tests for crate boundaries, CLI behavior, and serialized formats.
    crate 边界、CLI 行为、序列化格式这些地方要补上集成测试。
  • Prefer trait-based seams for mocking instead of container-heavy indirection.
    mock 时优先依靠 trait 边界,而不是把容器式间接层堆得很厚。
  • Use property tests where one handwritten example is not enough.
    凡是靠一两个手写样例压不住的逻辑,就考虑加性质测试。

Rust’s testing model feels lighter than a typical enterprise Java test stack, but that lightness is usually an advantage rather than a limitation.
Rust 的测试模型看起来比典型企业 Java 测试栈轻得多,但这种“轻”大多数时候反而是优点,不是短板。