mcpField
L
langchain4j-testing-strategies

langchain4j-testing-strategies

github.com/giuseppe-trisciuoglio测试与质量3653.7k 次安装7 周前更新
代码仓库

关于 langchain4j-testing-strategies

面向 LangChain4j Java 应用开发者的测试策略技能,覆盖 AI 服务、RAG 流程和工具执行。内容结合模型模拟、Testcontainers 集成测试与端到端验证。

主要功能

  1. 01用模拟模型进行单元测试
  2. 02使用 Testcontainers 测试真实服务
  3. 03验证 RAG 流程和工具执行
  4. 04测试流式处理、记忆与错误处理
  5. 05提供依赖配置和测试流程参考

适用场景

  1. 01隔离测试 LangChain4j AI 服务
  2. 02验证容器化模型集成
  3. 03测试 RAG 检索链
  4. 04检查工具执行的错误处理

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill langchain4j-testing-strategies

安装后在 Claude Code 中输入/langchain4j-testing-strategies确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
advanced-testing.md
integration-testing.md
testing-dependencies.md
unit-testing.md
workflow-patterns.md

详细介绍

LangChain4J 测试策略

概述

介绍使用模拟对象进行单元测试、使用 Testcontainers 进行集成测试,以及对 RAG 系统、AI Services 和工具执行进行端到端验证的模式。

适用场景

  • 测试 AI 服务:需要为使用 LangChain4j AiServices 的服务编写快速、隔离的测试时
  • 集成测试 LangChain4j 组件:使用 Testcontainers 测试真实的 ChatModel、EmbeddingModel 或 RAG 流程时
  • 模拟 AI 模型:需要确定性的响应,而不调用外部 API 时
  • 测试基于 LLM 的 Java 应用:验证 RAG 工作流、工具执行或检索链时

使用说明

1. 使用模拟对象进行单元测试

使用模拟模型进行快速、隔离的测试。请参阅 references/unit-testing.md。

ChatModel mockModel = mock(ChatModel.class);
when(mockModel.generate(any(String.class)))
    .thenReturn(Response.from(AiMessage.from("Mocked response")));

var service = AiServices.builder(AiService.class)
        .chatModel(mockModel)
        .build();
2. 配置测试依赖

设置 Maven/Gradle 依赖。请参阅 references/testing-dependencies.md。

  • langchain4j-test - 防护栏断言
  • testcontainers - 容器化测试
  • mockito - 模拟外部依赖
  • assertj - 流畅断言
3. 使用 Testcontainers 进行集成测试

使用真实服务进行测试。请参阅 references/integration-testing.md。

@Testcontainers
class OllamaIntegrationTest {
    @Container
    static GenericContainer<?> ollama = new GenericContainer<>(
        DockerImageName.parse("ollama/ollama:0.5.4")
    ).withExposedPorts(11434);

    @Test
    void shouldGenerateResponse() {
        // Verify container is healthy
        assertTrue(ollama.isRunning());
        await().atMost(30, TimeUnit.SECONDS)
            .until(() -> ollama.getLogs().contains("API server listening"));

        ChatModel model = OllamaChatModel.builder()
                .baseUrl(ollama.getEndpoint())
                .build();

        // Verify model responds before running tests
        assertDoesNotThrow(() -> model.generate("ping"));

        String response = model.generate("Test query");
        assertNotNull(response);
    }
}
4. 高级功能

流式传输、记忆和错误处理模式请参阅 references/advanced-testing.md。

5. 测试工作流

按照 references/workflow-patterns.md 中的测试金字塔进行测试:

  • 70% 单元测试:使用模拟对象,快速且隔离
  • 20% 集成测试:使用真实服务并进行健康检查
  • 10% 端到端测试:完整工作流
70% Unit Tests ─ Mock ChatModel, guardrails, edge cases
20% Integration Tests ─ Testcontainers, vector stores, RAG
10% End-to-End Tests ─ Complete user journeys
故障排查
  • 容器无法启动:检查 Docker 守护进程是否正在运行,确认镜像存在,并延长超时时间
  • 模型无响应:确认 baseUrl 正确,检查容器日志,并确保模型已加载
  • 测试超时:对于响应较慢的模型,延长 @Timeout 时长,并检查容器资源限制
  • 测试不稳定:添加重试逻辑,或在断言前进行健康检查

示例

单元测试
@Test
void shouldProcessQueryWithMock() {
    ChatModel mockModel = mock(ChatModel.class);
    when(mockModel.generate(any(String.class)))
        .thenReturn(Response.from(AiMessage.from("Test response")));

    var service = AiServices.builder(AiService.class)
            .chatModel(mockModel)
            .build();

    String result = service.chat("What is Java?");
    assertEquals("Test response", result);
}
使用 Testcontainers 进行集成测试
@Testcontainers
class RAGIntegrationTest {
    @Container
    static GenericContainer<?> ollama = new GenericContainer<>(
        DockerImageName.parse("ollama/ollama:0.5.4")
    );

    @BeforeAll
    static void waitForContainerReady() {
        await().atMost(60, TimeUnit.SECONDS)
            .until(() -> ollama.getLogs().contains("API server listening"));
    }

    @Test
    void shouldCompleteRAGWorkflow() {
        assertTrue(ollama.isRunning());

        var chatModel = OllamaChatModel.builder()
                .baseUrl(ollama.getEndpoint())
                .build();

        var embeddingModel = OllamaEmbeddingModel.builder()
                .baseUrl(ollama.getEndpoint())
                .build();

        var store = new InMemoryEmbeddingStore<>();
        var retriever = EmbeddingStoreContentRetriever.builder()
                .chatModel(chatModel)
                .embeddingStore(store)
                .embeddingModel(embeddingModel)
                .build();

        var assistant = AiServices.builder(RagAssistant.class)
                .chatLanguageModel(chatModel)
                .contentRetriever(retriever)
                .build();

        String response = assistant.chat("What is Spring Boot?");
        assertNotNull(response);
        assertTrue(response.contains("Spring"));
    }
}

最佳实践

  • 使用 @BeforeEach/@AfterEach 隔离测试
  • 单元测试中绝不调用真实 API;请使用模拟对象
  • 对外部服务调用添加 @Timeout
  • 测试成功和错误处理场景
  • 验证响应的连贯性和边界情况

常见模式

模拟策略
ChatModel mockModel = mock(ChatModel.class);
when(mockModel.generate(anyString())).thenReturn(Response.from(AiMessage.from("Mocked")));
when(mockModel.generate(eq("Hello"))).thenReturn(Response.from(AiMessage.from("Hi")));
when(mockModel.generate(contains("Java"))).thenReturn(Response.from(AiMessage.from("Java")));
断言辅助工具
assertThat(response).isNotNull().isNotEmpty();
assertThat(response).containsAll(expectedKeywords);
assertThat(response).doesNotContain("error");

参考文档

限制与警告

  • AI 响应具有非确定性;请使用模拟对象进行可靠的单元测试
  • 避免在测试中调用真实 API,以免产生费用和触发速率限制
  • 集成测试需要 Docker;请使用容器健康检查
  • RAG 测试需要正确填充嵌入存储
  • 基于模拟对象的测试无法保证实际的大模型行为;请辅以集成测试
  • 使用专用于测试的配置配置文件;绝不影响生产数据

评论

支持 Markdown