• 简体中文
  • 测试

    运行测试

    mvn test

    Surefire 运行所有匹配 **/*Test.***/*Spec.* 的类。

    测试框架

    • JUnit 5 — 测试运行器
    • Micronaut Test — 应用上下文注入
    • Micronaut HTTP Client — 控制器测试

    测试类模式

    @MicronautTest(transactional = false)
    class MyControllerTest {
    
        @Property(name = "h2.path", value = "mem:my_test_db")
        @Property(name = "datasources.default.url", value = "jdbc:h2:mem:my_test_db;DB_CLOSE_DELAY=-1")
        static class Config {}
    
        @Inject
        @Client("/")
        HttpClient httpClient;
    
        @Inject
        MyService myService;
    
        @Test
        void testEndpoint() {
            // 使用 retrieve() 进行更简洁的断言
            Map response = httpClient.toBlocking().retrieve(
                HttpRequest.GET("/endpoint").bearerAuth(token),
                Map.class
            );
            assertNotNull(response);
        }
    }

    测试隔离

    每个测试类使用内嵌 H2 数据库以避免冲突:

    @Property(name = "h2.path", value = "mem:unique_test_db")
    @Property(name = "datasources.default.url", value = "jdbc:h2:mem:unique_test_db;DB_CLOSE_DELAY=-1")

    DB_CLOSE_DELAY=-1 参数在测试期间保持数据库存活。

    HTTP 客户端模式

    使用 retrieve() 而非 exchange().getBody()

    // 好 — 出错时抛异常,直接返回 body
    Map response = httpClient.toBlocking().retrieve(
        HttpRequest.GET("/path").bearerAuth(token),
        Map.class
    );
    
    // 避免 — 某些有效响应返回 Optional.empty()
    Optional<Map> body = httpClient.toBlocking().exchange(
        HttpRequest.GET("/path").bearerAuth(token)
    ).getBody(Map.class);

    错误响应测试

    try {
        httpClient.toBlocking().retrieve(
            HttpRequest.POST("/path", body).bearerAuth(token),
            Map.class
        );
        fail("Expected exception");
    } catch (HttpClientResponseException e) {
        assertEquals(HttpStatus.FORBIDDEN, e.getStatus());
        Map error = e.getResponse().getBody(Map.class).orElse(null);
        assertEquals("M_FORBIDDEN", error.get("errcode"));
    }

    测试分类

    领域测试类覆盖范围
    认证流程AuthFlowTest注册、登录、令牌生命周期
    房间事件RoomEventTest发送、状态、成员关系
    同步V3SyncControllerTest长轮询、过滤器、分页
    端到端加密V3KeyControllerTest密钥上传/查询/领取
    媒体MediaControllerTest上传、下载、缩略图
    联邦P5FederationTest联邦端点
    管理AdminControllerTest管理 API
    P0 流程P0ClientFlowTest完整端到端集成
    路由RouteAuditTest所有路由响应正确

    诊断测试

    当测试因不透明错误失败时,创建最小化的诊断测试:

    @Test
    void diagnostic() {
        // 最小化复现失败场景
        // 捕获完整的响应体
        String body = httpClient.toBlocking().retrieve(
            HttpRequest.GET("/problematic/endpoint").bearerAuth(token),
            String.class
        );
        System.out.println("Response: " + body);
    }

    使用后清理诊断测试文件。