Unit tests cover modular logic that doesn’t require calls to external APIs.Naming convention: *.test.tsLocation: Place in a tests/ folder alongside the module being testedExample:
import { test, expect, describe } from "vitest";import { FakeChatModel } from "@langchain/core/utils/testing";test("should invoke fake chat model", async () => { const model = new FakeChatModel({}); const result = await model.invoke([["human", "Hello!"]]); expect(result.content).toBe("Hello!");});describe("MyComponent", () => { test("handles input correctly", () => { // Test implementation }); test("throws error on invalid input", () => { expect(() => myFunction(null)).toThrow(); });});
Running unit tests:
pnpm --filter langchain testpnpm --filter @langchain/core test
Integration tests cover logic that requires calls to external APIs.Naming convention: *.int.test.tsLocation: Place in a tests/ folder alongside the module being testedExample:
import { describe, test, expect } from "vitest";import { ChatOpenAI } from "../index.js";import { HumanMessage } from "@langchain/core/messages";test("Test ChatOpenAI Generate", async () => { const chat = new ChatOpenAI({ model: "gpt-4o-mini", maxTokens: 10, }); const message = new HumanMessage("Hello!"); const result = await chat.invoke([message]); expect(typeof result.content).toBe("string");});
Environment setup:Most integration tests require API credentials. Create a .env file based on .env.example:
# Example .env fileOPENAI_API_KEY=your_key_hereANTHROPIC_API_KEY=your_key_herePINECONE_API_KEY=your_key_here
Running integration tests:
# All integration testspnpm --filter langchain test:integration# Single integration testpnpm --filter langchain test:single src/chat_models/tests/index.int.test.ts
Integration tests can be slow and may incur API costs. We recommend running specific tests with test:single during development.
Standard tests ensure provider integrations conform to LangChain interfaces. They’re provided by the @langchain/standard-tests package.Naming convention: *.standard.test.ts (unit) and *.standard.int.test.ts (integration)Example for chat models:
import { ChatModelUnitTests } from "@langchain/standard-tests";import { AIMessageChunk } from "@langchain/core/messages";import { MyChatModel } from "../index.js";class MyChatModelStandardUnitTests extends ChatModelUnitTests< MyChatModelCallOptions, AIMessageChunk> { constructor() { super({ Cls: MyChatModel, chatModelHasToolCalling: true, chatModelHasStructuredOutput: true, constructorArgs: { model: "my-model", }, }); } // Override specific tests if needed async testModelCanStreamUsage() { // Custom implementation }}const testClass = new MyChatModelStandardUnitTests();// Run all standard teststest("MyChatModel standard tests", async () => { await testClass.runTests();});
Running standard tests:
# Unit standard testspnpm --filter @langchain/openai test:standard:unit# Integration standard tests pnpm --filter @langchain/openai test:standard:int# All standard testspnpm test:standard
# Run all unit testspnpm test:unit# Run unit tests for specific packagepnpm --filter langchain testpnpm --filter @langchain/core test# Run integration testspnpm --filter langchain test:integration# Run single test filepnpm --filter langchain test:single src/tests/my-test.test.ts# Watch modepnpm --filter langchain test:watch# With coveragepnpm --filter langchain test --coverage
For unit tests, use fake implementations to avoid external dependencies:
import { FakeChatModel } from "@langchain/core/utils/testing";import { FakeListLLM } from "@langchain/core/utils/testing";test("test with fake chat model", async () => { const model = new FakeChatModel({}); // Test your logic});test("test with fake LLM", async () => { const llm = new FakeListLLM({ responses: ["response 1", "response 2"] }); // Test your logic});