rust-testing-advanced

Advanced Rust testing anti-patterns and corrections — cfg(test) placement, expect() over unwrap(), mockall expectation ordering, executor mixing (#[tokio::test] vs block_on), PgPool isolation with

8 stars

Best use case

rust-testing-advanced is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Advanced Rust testing anti-patterns and corrections — cfg(test) placement, expect() over unwrap(), mockall expectation ordering, executor mixing (#[tokio::test] vs block_on), PgPool isolation with

Teams using rust-testing-advanced should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/rust-testing-advanced/SKILL.md --create-dirs "https://raw.githubusercontent.com/marvinrichter/clarc/main/skills/rust-testing-advanced/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/rust-testing-advanced/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How rust-testing-advanced Compares

Feature / Agentrust-testing-advancedStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Advanced Rust testing anti-patterns and corrections — cfg(test) placement, expect() over unwrap(), mockall expectation ordering, executor mixing (#[tokio::test] vs block_on), PgPool isolation with

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Rust Testing — Advanced Patterns

This skill extends `rust-testing` with anti-patterns and corrections. Load `rust-testing` first.

## When to Activate

- Reviewing Rust test code for common mistakes
- Debugging flaky tests caused by shared pool state
- Diagnosing mock setup ordering errors (already-moved mock)
- Fixing async test executor mismatches
- Reducing release binary size from mis-placed test code

---

## Anti-Patterns

### Placing Tests Outside #[cfg(test)] in Source Files

**Wrong:**
```rust
// src/domain/discount.rs
pub fn apply_discount(price: f64, tier: CustomerTier) -> f64 { /* ... */ }

#[test]  // Compiles into release builds — wastes binary size
fn standard_no_discount() {
    assert_eq!(apply_discount(100.0, CustomerTier::Standard), 100.0);
}
```

**Correct:**
```rust
pub fn apply_discount(price: f64, tier: CustomerTier) -> f64 { /* ... */ }

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

    #[test]
    fn standard_no_discount() {
        assert_eq!(apply_discount(100.0, CustomerTier::Standard), 100.0);
    }
}
```

**Why:** Without `#[cfg(test)]`, test code and its dependencies are compiled into release binaries, increasing binary size and compile time.

### Using unwrap() in Tests Instead of Descriptive Assertions

**Wrong:**
```rust
#[test]
fn save_user() {
    let user = repo.save(&new_user()).await.unwrap(); // Panic message is useless
    assert_eq!(user.email, "alice@test.com");
}
```

**Correct:**
```rust
#[test]
async fn save_user() {
    let user = repo.save(&new_user()).await
        .expect("saving a valid user should not fail");
    assert_eq!(user.email, "alice@test.com");
}
```

**Why:** `expect("context")` produces a meaningful panic message that explains what went wrong at the test boundary, making failures far easier to diagnose.

### Setting Up Mock Expectations After Creating the Service

**Wrong:**
```rust
let service = UserService::new(Arc::new(mock)); // mock moved in
mock.expect_save().returning(|_| Ok(saved_user())); // compile error: already moved
```

**Correct:**
```rust
let mut mock = MockUserRepository::new();
mock.expect_save()
    .times(1)
    .returning(|_| Ok(saved_user()));

let service = UserService::new(Arc::new(mock)); // move after setup
```

**Why:** Expectations must be configured before the mock is moved into the service under test; setting them up first also makes the test intent readable at a glance.

### Running Async Tests with std::thread::block_on Instead of #[tokio::test]

**Wrong:**
```rust
#[test]
fn fetch_returns_user() {
    let result = futures::executor::block_on(service.fetch(1)); // Wrong executor
    assert!(result.is_ok());
}
```

**Correct:**
```rust
#[tokio::test]
async fn fetch_returns_user() {
    let result = service.fetch(1).await;
    assert!(result.is_ok());
}
```

**Why:** Mixing executors causes panics or silent hangs; `#[tokio::test]` provides a proper single-threaded Tokio runtime that matches the runtime used in production.

### Sharing a Single PgPool Across All Integration Tests

**Wrong:**
```rust
// tests/common/mod.rs
static POOL: Lazy<PgPool> = Lazy::new(|| { /* ... */ });
// Tests share state — inserts from one test pollute another
```

**Correct:**
```rust
#[sqlx::test]  // sqlx::test injects a fresh, isolated pool per test
async fn find_by_id_returns_none(pool: PgPool) {
    let repo = PostgresUserRepo::new(pool);
    assert!(repo.find_by_id(9999).await.unwrap().is_none());
}
```

**Why:** `#[sqlx::test]` wraps each test in its own transaction that is rolled back after the test, guaranteeing isolation without manual cleanup.

## Reference

- `rust-testing` — core testing patterns (unit, mocks, integration, benchmarks, CI)

Related Skills

zero-trust-patterns

8
from marvinrichter/clarc

Zero-Trust security patterns — mTLS between microservices (Istio/SPIFFE), SPIRE workload identity, OPA/Envoy authorization, NetworkPolicy default-deny-all, short-lived credentials, service mesh security, and Kubernetes RBAC hardening.

visual-testing

8
from marvinrichter/clarc

Visual Regression Testing: tool comparison (Chromatic/Percy/Playwright screenshots/BackstopJS), pixel-diff vs AI-based comparison, baseline management, flakiness strategies (masks, tolerances, waitForLoadState), CI integration with GitHub Actions, and Storybook integration.

typescript-testing

8
from marvinrichter/clarc

TypeScript testing patterns: Vitest for unit/integration, Playwright for E2E, MSW for API mocking, Testing Library for React components. Core TDD methodology for TypeScript/JavaScript projects.

typescript-patterns-advanced

8
from marvinrichter/clarc

Advanced TypeScript — mapped types, template literal types, conditional types, infer, type guards, decorators, async patterns, testing with Vitest/Jest, and performance. Extends typescript-patterns.

tdd-workflow-advanced

8
from marvinrichter/clarc

TDD anti-patterns — writing code before tests, testing implementation details instead of behavior, using waitForTimeout as a sync strategy, chaining tests that share state, mocking the system under test instead of its dependencies.

swift-testing

8
from marvinrichter/clarc

Swift testing patterns: Swift Testing framework (Swift 6+), XCTest for UI tests, async/await test cases, actor testing, Combine testing, and XCUITest for UI automation. TDD for Swift/SwiftUI.

swift-protocol-di-testing

8
from marvinrichter/clarc

Protocol-based dependency injection for testable Swift code — mock file system, network, and external APIs using focused protocols and Swift Testing.

swift-patterns-advanced

8
from marvinrichter/clarc

Advanced Swift patterns — property wrappers, result builders, Combine basics, opaque & existential types, macro system, advanced generics, and performance optimization. Extends swift-patterns.

serverless-patterns-advanced

8
from marvinrichter/clarc

Advanced Serverless patterns — Lambda idempotency (Lambda Powertools + DynamoDB persistence layer), Lambda cost model (pricing formula, break-even vs containers), and CloudWatch Insights observability queries for cold starts, duration, and errors.

security-review-advanced

8
from marvinrichter/clarc

Security anti-patterns — localStorage token storage (XSS risk), trusting client-side authorization checks, reflecting full error details to clients, blacklist vs whitelist input validation, using npm install instead of npm ci in CI pipelines.

scala-testing

8
from marvinrichter/clarc

Scala testing with ScalaTest, MUnit, and ScalaCheck: FunSpec/FlatSpec test structure, property-based testing with forAll, mocking with MockitoSugar, Cats Effect testing with munit-cats-effect (runTest/IOSuite), ZIO Test, Testcontainers-Scala for database integration tests, and CI integration with sbt. Use when writing or reviewing Scala tests.

rust-web-patterns

8
from marvinrichter/clarc

Axum HTTP handlers, Serde serialization, async channels, iterator patterns, trait objects, configuration, and WebAssembly target for Rust web services.