---
description: Rust Testing
alwaysApply: false
---

# Rust Testing

`cargo test` runs unit tests, integration tests, and doc tests in one command.

## Unit Tests

```rust
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn freezing_point() {
        assert!((celsius_to_fahrenheit(0.0) - 32.0).abs() < f64::EPSILON);
    }

    #[test]
    fn boiling_point() {
        assert!((celsius_to_fahrenheit(100.0) - 212.0).abs() < f64::EPSILON);
    }
}
```

## Testing Errors

```rust
#[test]
fn empty_name_fails_validation() {
    let input = CreateUserInput { name: "".into(), email: "a@b.com".into() };
    assert!(matches!(validate_user(&input), Err(ValidationError::EmptyField { .. })));
}

#[test]
#[should_panic(expected = "index out of bounds")]
fn panics_on_out_of_bounds() { let _ = vec![1, 2, 3][10]; }
```

## Property-Based Testing

```rust
proptest! {
    #[test]
    fn round_trips(name in "[a-zA-Z]{1,50}", age in 0u32..150) {
        let user = User { name, age };
        let json = serde_json::to_string(&user)?;
        let decoded: User = serde_json::from_str(&json)?;
        assert_eq!(user, decoded);
    }
}
```

## Trait-Based DI (Prefer Over Mocking)

```rust
trait Clock { fn now(&self) -> DateTime<Utc>; }
struct FakeClock(DateTime<Utc>);
impl Clock for FakeClock { fn now(&self) -> DateTime<Utc> { self.0 } }
// Inject FakeClock in tests for deterministic time
```

## Anti-Patterns

```rust
// Never: Tests depending on execution order — each runs in own thread
// Never: Assertions without messages in complex tests
assert!(result.is_ok(), "input {input:?} got {result:?}");
// Never: Flaky tests — fix the race condition or timing dependency
```
