Miko 框架系列(十四):集成测试

Miko 框架系列(十四):集成测试

注意:此文章主要为了给支持联网搜索的AI提供RAG,此项目还在开发阶段,不建议用于生产。

测试是保证软件质量的关键环节。在 Web 开发中,集成测试(Integration Testing)尤为重要,因为它能验证路由、中间件、提取器和业务逻辑是否作为一个整体协同工作。

Miko 提供了一个强大的 TestClient 工具,专门用于进行**进程内(In-Process)**的集成测试。它不仅速度极快,而且能模拟真实的请求处理流程。

1. 核心优势

  • 极速执行:绕过网络协议栈,直接在内存中分发请求,测试运行速度比通过 HTTP 接口测试快数倍。
  • 无需端口:测试在同一个进程内运行,不需要绑定 TCP 端口,避免了端口冲突问题,也支持并行运行测试。
  • 全链路覆盖:完整触发路由解析、请求提取器、中间件(Layers)以及依赖注入逻辑。
  • 环境一致性 :配合 Miko 的 build 模式,确保测试环境与生产环境配置完全一致。

2. 启用测试支持

首先,在 Cargo.toml 中启用 test feature:

toml 复制代码
[dev-dependencies]
miko = { version = "0.7", features = ["test", "full"] }

3. 基础用法:测试 Router

如果你只想测试一部分路由逻辑,可以直接在 Router 实例上调用 test_client()

rust 复制代码
use miko::{Router, TestClient};

#[tokio::test]
async fn test_basic_router() {
    let mut router = Router::new();
    router.get("/ping", || async { "pong" });

    // 创建测试客户端
    let client = router.test_client();

    // 发送请求并断言
    client.get("/ping")
        .send()
        .await
        .assert_status(200)
        .assert_text("pong");
}

4. 进阶用法:全量应用测试

对于实际应用,我们通常需要测试完整的应用程序,包括依赖注入、配置和全局中间件。Miko 推荐使用 build 模式来进行全量测试。

第一步:改造应用入口

src/main.rs 中,将应用构建逻辑抽取出来,并使用 #[miko(build)] 宏。这会生成一个可供测试调用的构建函数。

rust 复制代码
// src/main.rs
use miko::*;

// 添加 build 参数
// 这会生成一个名为 `create_app` 的 public async 函数
#[miko(build)] 
async fn main() {
    let mut router = Router::new();
    router.get("/", || async { "Hello Miko" });
    // ... 注册其他路由和组件
}

第二步:编写集成测试

tests/ 目录下,引用主程序模块,并使用生成好的 create_app 函数。

rust 复制代码
// tests/app_test.rs

// 引用 src/main.rs
#[path = "../src/main.rs"]
mod app;

#[tokio::test]
async fn test_full_application() {
    // 1. 获取全量配置的应用实例 (包括 DI 容器初始化、配置加载等)
    let mut app = app::create_app().await;

    // 2. 创建客户端
    let client = app.test_client();

    // 3. 执行测试
    client.get("/").send().await.assert_text("Hello Miko");
}

5. 构造请求与断言

TestClient 提供了类似 reqwest 的链式 API,让你能轻松构造各种请求,并对响应进行丰富的断言。

rust 复制代码
use serde_json::json;

#[tokio::test]
async fn test_create_user() {
    // ... 初始化 client ...

    let res = client.post("/api/users")
        .header("Authorization", "Bearer my-token")
        .json(&json!({ 
            "username": "test_user", 
            "email": "test@example.com" 
        }))
        .send()
        .await;

    // 状态码断言
    res.assert_status(201);
    
    // Header 断言
    res.assert_header("Content-Type", "application/json");

    // JSON Body 断言
    res.assert_json(json!({
        "success": true,
        "username": "test_user"
    }));
}

常用断言方法

  • assert_ok(): 断言状态码为 2xx。
  • assert_status(code): 断言特定的 HTTP 状态码。
  • assert_header(key, value): 断言响应头存在且值匹配。
  • assert_text(expected): 断言响应体文本内容。
  • assert_json(expected): 断言响应体匹配给定的 JSON (支持部分匹配)。
  • assert_contains(text): 断言响应体包含特定文本。

6. 测试依赖注入 (DI)

当使用 create_app() 模式时,DI 容器会自动初始化。如果你需要手动控制,可以使用 miko::auto::init_container()

rust 复制代码
#[tokio::test]
async fn test_with_di() {
    // 手动初始化 DI 容器
    miko::auto::init_container().await;
    
    // ...
}

总结

Miko 的 TestClient 为开发者提供了一种高效、可靠的测试手段。通过在进程内模拟请求,它不仅消除了网络开销,还保证了测试环境与生产环境的高度一致性。配合 #[miko(build)] 模式,你可以轻松编写出覆盖率高、运行速度快的集成测试套件。


下一篇预告:Miko 框架系列(十五):版本更新与新特性总览

相关推荐
代码笔耕2 小时前
我们这样设计消息中心,解决了业务反复折腾的顽疾
java·后端·架构
chenyuhao20242 小时前
Linux系统编程:多线程同步与单例模式
linux·服务器·c++·后端·单例模式
唐装鼠2 小时前
Rust Turbofish 语法详解(deepseek)
开发语言·后端·rust
Source.Liu2 小时前
【Rust】字符串类型全览:从 UTF-8 到系统路径
rust
码luffyliu2 小时前
Go 语言并发编程:为何它能甩开 Java 等传统后端语言?
java·后端·golang·go
青梅主码2 小时前
微软最新发布《微软2025年新未来工作报告》:AI 如何帮助团队和组织实现集体生产力的提升?
后端
武子康3 小时前
大数据-193 Apache Tez 实战:Hive on Tez 安装配置、DAG原理与常见坑
大数据·后端·apache
青石路3 小时前
用了MySQL的INSERT ON DUPLICATE KEY UPDATE,怎么还报唯一索引冲突错误
后端·sql·mysql
唐装鼠3 小时前
Rust 中的 `parse` 方法详解(deepseek)
开发语言·后端·rust