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 框架系列(十五):版本更新与新特性总览

相关推荐
上进小菜猪14 分钟前
基于 YOLOv8 的昆虫智能识别工程实践 [目标检测完整源码]
后端
superman超哥21 分钟前
Rust 异步递归的解决方案
开发语言·后端·rust·编程语言·rust异步递归
Mr -老鬼1 小时前
Rust 的优雅和其他语言的不同之处
java·开发语言·rust
weixin_531651811 小时前
Rust 的所有权机制
java·开发语言·rust
开心就好20251 小时前
iOS Crash日志全面解析:结构、类型与分析方法
后端
毕设源码-钟学长1 小时前
【开题答辩全过程】以 基于Spring Boot的社区养老服务管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
nbsaas-boot1 小时前
slice / map 在 Go GC 与内存碎片上的真实成本
开发语言·后端·golang
数据小馒头1 小时前
拒绝循环写库:MySQL 批量插入、Upsert 与跨表更新的高效写法
后端
子洋1 小时前
基于远程开发的大型前端项目实践
运维·前端·后端
sheji34162 小时前
【开题答辩全过程】以 基于spring boot的停车管理系统为例,包含答辩的问题和答案
java·spring boot·后端