Internal testing utilities for Quarkus LangChain4j that provide a WiremockAware base class for mocking HTTP-based LLM API calls in integration tests. NOTE: This is an internal-only module not published to Maven Central.
Internal testing utilities for the Quarkus LangChain4j extension ecosystem, providing a streamlined base class that integrates Wiremock mocking capabilities with Quarkus test infrastructure for mocking HTTP-based LLM API calls during testing.
IMPORTANT: This is an internal-only testing module used within the quarkus-langchain4j project. It is NOT published to Maven Central. To use this module, you must build it from source or be working within the quarkus-langchain4j repository.
Since this module is not published to Maven Central, you must build it locally:
git clone https://github.com/quarkiverse/quarkus-langchain4j.git
cd quarkus-langchain4j
git checkout 1.7.4
cd testing-internal
mvn clean installAfter building from source, add to your Maven pom.xml:
<dependency>
<groupId>io.quarkiverse.langchain4j</groupId>
<artifactId>quarkus-langchain4j-testing-internal</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>import io.quarkiverse.langchain4j.testing.internal.WiremockAware;Extend WiremockAware in your test class to gain access to Wiremock testing utilities:
import io.quarkiverse.langchain4j.testing.internal.WiremockAware;
import io.quarkus.test.QuarkusUnitTest;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static org.assertj.core.api.Assertions.assertThat;
public class MyLangChainTest extends WiremockAware {
@RegisterExtension
static final QuarkusUnitTest unitTest = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addAsResource(new StringAsset(
"llm.api.url=" + WiremockAware.wiremockUrlForConfig("/v1/chat")
), "application.properties"));
@BeforeEach
public void setup() {
// Register mock responses
wiremock().register(
post(urlEqualTo("/v1/chat"))
.willReturn(aResponse()
.withHeader("Content-Type", "application/json")
.withBody("{\"response\": \"Hello from mock!\"}")
)
);
}
@Test
public void testLLMInteraction() {
// Your test code that calls the LLM API
// ...
// Verify the request
LoggedRequest request = singleLoggedRequest();
assertThat(request.getUrl()).isEqualTo("/v1/chat");
assertThat(request.getMethod().toString()).isEqualTo("POST");
}
}Generate Wiremock URL templates for use in test configuration properties before port resolution.
public static String wiremockUrlForConfig()Returns a Wiremock URL template with port placeholder: "http://localhost:${quarkus.wiremock.devservices.port}". Use this in configuration properties (e.g., application.properties) to reference the Wiremock server before the port is resolved at runtime.
Example:
new StringAsset(
"my.service.base-url=" + WiremockAware.wiremockUrlForConfig()
)public static String wiremockUrlForConfig(String path)Parameters:
path (String) - URL path to append to the base URL (with or without leading slash)Returns: String - Wiremock URL template with the specified path appended
Automatically handles:
Example:
WiremockAware.wiremockUrlForConfig("/api/chat") // Returns: http://localhost:${...}/api/chat
WiremockAware.wiremockUrlForConfig("api/chat") // Returns: http://localhost:${...}/api/chat
WiremockAware.wiremockUrlForConfig("") // Returns: http://localhost:${...}Get fully resolved Wiremock URLs with actual port numbers for use in test methods after Quarkus starts.
public String resolvedWiremockUrl()Returns the fully resolved Wiremock base URL with actual port number: "http://localhost:<port>". Call this in test methods or lifecycle methods (e.g., @BeforeEach, @AfterEach) after Quarkus has started.
public String resolvedWiremockUrl(String path)Parameters:
path (String) - URL path to append to the base URL (with or without leading slash)Returns: String - Fully resolved Wiremock URL with the specified path
Automatically handles:
Example:
resolvedWiremockUrl("/api/chat") // Returns: http://localhost:8080/api/chat (actual port)
resolvedWiremockUrl("api/chat") // Returns: http://localhost:8080/api/chat
resolvedWiremockUrl("") // Returns: http://localhost:8080Get or create WireMock client instances for stubbing HTTP responses and verifying requests.
protected WireMock wiremock()Returns a WireMock client instance connected to the resolved Wiremock port. The client is lazily initialized on first call and cached for subsequent calls. Use this client to:
register()getServeEvents()resetRequests() or resetMappings()Example:
wiremock().register(
get(urlEqualTo("/api/data"))
.willReturn(aResponse().withBody("mock data"))
);protected WireMock wiremock(Integer port)Parameters:
port (Integer) - Specific port number to connect the WireMock client toReturns: WireMock - WireMock client instance for the specified port
Use this when working with multiple Wiremock instances on different ports.
Get the actual port number that Wiremock devservices is running on.
protected Integer getResolvedWiremockPort()Returns the resolved Wiremock devservices port by reading the quarkus.wiremock.devservices.port configuration property value.
Reset Wiremock state between tests or before verifications.
protected void resetRequests()Clears all logged requests from Wiremock. Use this to clean up state between test methods or before request verifications to ensure only relevant requests are captured.
Example:
@BeforeEach
public void setup() {
resetRequests(); // Start with clean slate
// Register stubs...
}protected void resetMappings()Clears all stub mappings from Wiremock. Use this to remove all registered stubs, useful for test cleanup or when you need to completely reconfigure the mock server.
Retrieve and verify logged HTTP requests made to the Wiremock server.
protected LoggedRequest singleLoggedRequest()Returns: LoggedRequest - The single logged request captured by Wiremock
Retrieves the only logged request and asserts that exactly one request was made. Fails with an AssertJ assertion error if zero or more than one request was logged. The returned LoggedRequest provides access to:
getUrl())getMethod())getHeader(String))getBody(), getBodyAsString())Example:
LoggedRequest request = singleLoggedRequest();
assertThat(request.getUrl()).isEqualTo("/api/endpoint");
assertThat(request.getMethod().toString()).isEqualTo("POST");
assertThat(request.getHeader("Authorization")).isEqualTo("Bearer token");protected LoggedRequest singleLoggedRequest(WireMock wireMock)Parameters:
wireMock (WireMock) - Specific WireMock instance to query for logged requestsReturns: LoggedRequest - The single logged request from the specified WireMock instance
Use this variant when working with multiple Wiremock instances to verify requests on a specific instance.
protected byte[] requestBodyOfSingleRequest()Returns: byte[] - The body bytes of the single logged request
Convenience method that calls singleLoggedRequest() and returns the request body bytes. Useful when you need to verify request body content.
Example:
byte[] body = requestBodyOfSingleRequest();
String bodyString = new String(body, StandardCharsets.UTF_8);
assertThat(bodyString).contains("\"query\":\"test\"");protected byte[] getRequestBody(ServeEvent serveEvent)Parameters:
serveEvent (ServeEvent) - Wiremock serve event containing the request to extract body fromReturns: byte[] - The request body bytes
Extracts the request body from a serve event. Asserts that the body is not empty before returning. Use this when iterating through multiple serve events.
Example:
List<ServeEvent> events = wiremock().getServeEvents();
for (ServeEvent event : events) {
byte[] body = getRequestBody(event);
// Process body...
}The following types from external libraries are used in the API:
// From com.github.tomakehurst.wiremock.client
class WireMock {
void register(MappingBuilder mappingBuilder);
List<ServeEvent> getServeEvents();
void resetRequests();
void resetMappings();
}// From com.github.tomakehurst.wiremock.verification
class LoggedRequest {
String getUrl();
RequestMethod getMethod();
String getHeader(String key);
byte[] getBody();
String getBodyAsString();
}// From com.github.tomakehurst.wiremock.stubbing
class ServeEvent {
LoggedRequest getRequest();
}This utility class is designed to work with Quarkus test infrastructure:
@QuarkusTest: Use in integration tests with full Quarkus application contextQuarkusUnitTest: Use with JUnit 5 extension for more lightweight tests${quarkus.wiremock.devservices.port} is resolved at runtime via MicroProfile ConfigThis class exists as an alternative to io.quarkiverse.wiremock.devservice.ConnectWireMock which does not work well with QuarkusUnitTest. WiremockAware provides a reliable base class that works consistently across different Quarkus test scenarios.
Tests using this utility require the following dependencies:
<dependencies>
<!-- Target testing module (must be built from source) -->
<dependency>
<groupId>io.quarkiverse.langchain4j</groupId>
<artifactId>quarkus-langchain4j-testing-internal</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
<!-- Quarkus JUnit 5 Internal (provides QuarkusUnitTest and ShrinkWrap) -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
<!-- Wiremock support for Quarkus -->
<dependency>
<groupId>io.quarkiverse.wiremock</groupId>
<artifactId>quarkus-wiremock-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Wiremock standalone -->
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock-standalone</artifactId>
<scope>test</scope>
</dependency>
<!-- AssertJ for fluent assertions -->
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<!-- JUnit 5 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>Note: This module is built as part of the quarkus-langchain4j project. Use the Quarkus BOM for version management, and ensure compatibility between Quarkus core and Quarkiverse extensions. The quarkus-junit5-internal dependency provides access to QuarkusUnitTest and ShrinkWrap classes.
Install with Tessl CLI
npx tessl i tessl/maven-io-quarkiverse-langchain4j--quarkus-langchain4j-testing-internal