Package dev.langchain4j.test.mock


package dev.langchain4j.test.mock
Model mocks for tests: they need no network, answer the way a test tells them to, and record the requests they receive. Add dev.langchain4j:langchain4j-test with test scope to use them.

All six mocks, MockChatModel, MockStreamingChatModel, MockDecisionModel, MockEmbeddingModel, MockScoringModel and MockModerationModel, follow a script: every that... method creates a mock with its first step (one step per message for the message-list forms), every then... method adds a step, each step answers one request, a request after the last step fails, and thenRepeats() at the end of the script answers every further request with the last step. A step can also compute its answer from the request, for example MockChatModel.thatResponds(request -> answer). A script can also let a request fail and the next one succeed, for example MockEmbeddingModel.thatFails(exception).thenEmbeds(0.1f, 0.2f), to test your own retry logic. A mock that is called more than once ends its script with thenRepeats().

On every mock, thatResponds(...) and thenResponds(...) give a step as the whole response of the model, for example an EmbeddingResponse: the request is answered with exactly that response, including its metadata, for example the token usage of an embedding call in a cost test, also when it does not fit the request, for example to test how your code handles a provider that returns too few embeddings. Only the decision mock still checks the answers like a real model does. On the chat mocks, they also take the text or the message of the answer.

A mock remembers which steps were taken and which requests it received, so create a new one for each test, for example by replacing the model bean for each test. In Quarkus, QuarkusMock.installMockForType(...) does that. In Spring, @TestBean replaces the bean once per cached Spring context, which is usually per test class; for a new mock per test, build the context in the test, for example with ApplicationContextRunner. Give the @TestBean field the type of the bean it replaces, for example ChatModel: for a field of the mock's type, Spring finds no bean to replace and adds the mock as a second model bean. A script that ends with thenRepeats() can be shared between tests, but its requests() then hold the requests of every test that used it. A script without thenRepeats() that is shared between tests fails as soon as it runs out. A mock keeps every request it receives, so it is not meant for load tests or other long runs.

A mock can be called from several threads at once. The steps of a script are taken in the order the requests arrive, so to answer concurrent requests, compute the answer from the request, for example MockChatModel.thatResponds(request -> answer).thenRepeats(). Set the options, such as withListeners(...), withSupportedCapabilities(...) and withTokenUsage(...), before the first request.