Multi-module test support framework for Embabel Agent applications providing integration testing, mock AI services, and test configuration utilities
Complete type definitions for Embabel Agent Test Support framework.
/**
* Abstract base class for Mockito-based integration tests.
* Provides Spring Boot test context with mocked LLM operations.
*/
@SpringBootTest
@TestPropertySource(properties = {
"embabel.models.default-llm=test-model",
"embabel.agent.verbosity.debug=true",
"spring.shell.interactive.enabled=false",
"spring.shell.noninteractive.enabled=false"
})
public abstract class EmbabelMockitoIntegrationTest {
/** AgentPlatform instance for running agents in tests */
@Autowired
protected AgentPlatform agentPlatform;
/** Mocked LLM operations for stubbing and verification */
@MockitoBean
protected LlmOperations llmOperations;
// Stubbing methods
protected <T> OngoingStubbing<T> whenCreateObject(
Predicate<String> promptMatcher,
Class<T> outputClass
);
protected <T> OngoingStubbing<T> whenCreateObject(
Predicate<String> promptMatcher,
Class<T> outputClass,
Predicate<LlmInteraction> llmInteractionPredicate
);
protected OngoingStubbing<String> whenGenerateText(
Predicate<String> promptMatcher
);
protected OngoingStubbing<String> whenGenerateText(
Predicate<String> promptMatcher,
Predicate<LlmInteraction> llmInteractionMatcher
);
// Verification methods
protected <T> void verifyCreateObject(
Predicate<String> promptMatcher,
Class<T> outputClass
);
protected <T> void verifyCreateObject(
Predicate<String> promptMatcher,
Class<T> outputClass,
Predicate<LlmInteraction> llmInteractionMatcher
);
protected void verifyGenerateText(
Predicate<String> promptMatcher
);
protected void verifyGenerateText(
Predicate<String> promptMatcher,
Predicate<LlmInteraction> llmInteractionMatcher
);
protected void verifyNoInteractions();
protected void verifyNoMoreInteractions();
// Argument capture methods
protected ArgumentCaptor<String> capturePrompt();
protected ArgumentCaptor<LlmInteraction> captureLlmInteraction();
protected <T> ArgumentCaptor<Class<T>> captureOutputClass();
}Module: embabel-agent-test Package: com.embabel.agent.test.integration
/**
* Fake embedding model that generates random embeddings for testing.
* Implements Spring AI's EmbeddingModel interface.
*/
data class FakeEmbeddingModel(
/** The dimension size of generated embeddings (default: 1536) */
val dimensions: Int = 1536
) : EmbeddingModel {
/**
* Generate a random embedding for a single document.
*/
override fun embed(document: Document): FloatArray
/**
* Generate random embeddings for multiple text inputs.
*/
override fun embed(texts: List<String>): MutableList<FloatArray>
/**
* Process an EmbeddingRequest and return an EmbeddingResponse.
*/
override fun call(request: EmbeddingRequest): EmbeddingResponse
}Module: embabel-agent-test-common Package: com.embabel.common.test.ai
/**
* Spring test configuration providing fake AI service beans.
*/
@TestConfiguration
class FakeAiConfiguration {
/**
* Fake LLM service bean for "cheapest" model tier (gpt-4o-mini).
*/
@Bean
fun cheapest(): LlmService<*>
/**
* Fake LLM service bean for "best" model tier (gpt-4o).
*/
@Bean
fun best(): LlmService<*>
/**
* Fake embedding service bean with 1536 dimensions.
*/
@Bean
fun embedding(): EmbeddingService
}Module: embabel-agent-test-internal Package: com.embabel.common.test.ai.config
/**
* Abstract base class for testing OptionsConverter implementations.
* Provides automatic core value preservation testing.
*/
abstract class OptionsConverterTestSupport<O : ChatOptions>(
/** The OptionsConverter instance to test */
protected val optionsConverter: OptionsConverter<O>
) {
/**
* Test that verifies core LLM option values are preserved.
* Automatically tests temperature, topP, and frequencyPenalty.
*/
@Test
fun `should preserve core values`()
}Module: embabel-agent-test-internal Package: com.embabel.agent.test.models
/**
* Interface for LLM operations - createObject and generateText.
*/
interface LlmOperations {
/**
* Create a structured object from LLM response.
*/
<T> T createObject(
List<? extends Message> messages,
LlmInteraction llmInteraction,
Class<T> outputClass,
Object context,
Object metadata
);
/**
* Generate text response from LLM.
*/
String generateText(
List<? extends Message> messages,
LlmInteraction llmInteraction
);
}Package: com.embabel.agent.spi
/**
* Configuration for LLM interaction including model and parameters.
*/
class LlmInteraction {
/** Get the model name (e.g., "gpt-4") */
String getModel();
/** Get the temperature setting (0.0 to 2.0) */
Double getTemperature();
/** Get the maximum tokens setting */
Integer getMaxTokens();
/** Get the tool groups for function calling */
List<String> getToolGroups();
/** Get the top-p (nucleus sampling) setting */
Double getTopP();
/** Get the frequency penalty setting */
Double getFrequencyPenalty();
}Package: com.embabel.agent.core.support
/**
* Service interface for LLM operations.
*/
interface LlmService<T : ChatOptions> {
/**
* Generate text from a simple prompt.
*/
fun generate(prompt: String): String
/**
* Generate text from a list of messages.
*/
fun generate(messages: List<Message>): String
/**
* Create a structured object from messages.
*/
fun <R> createObject(messages: List<Message>, outputClass: Class<R>): R
}Package: com.embabel.agent.spi
/**
* Service interface for embedding operations.
*/
interface EmbeddingService {
/**
* Embed a single text string.
*/
fun embed(text: String): FloatArray
/**
* Embed multiple text strings.
*/
fun embed(texts: List<String>): List<FloatArray>
/**
* Embed a document with metadata.
*/
fun embed(document: Document): FloatArray
}Package: com.embabel.agent.spi
/**
* Converter from framework-agnostic LlmOptions to provider-specific ChatOptions.
*/
interface OptionsConverter<T : ChatOptions> {
/**
* Convert LlmOptions to provider-specific ChatOptions.
*/
fun convert(options: LlmOptions): T
}Package: com.embabel.common.ai.model
/**
* Framework-agnostic LLM options.
*/
class LlmOptions {
/** Temperature setting (0.0 to 2.0) */
val temperature: Double?
/** Top-p (nucleus sampling) setting (0.0 to 1.0) */
val topP: Double?
/** Frequency penalty (-2.0 to 2.0) */
val frequencyPenalty: Double?
/** Maximum tokens to generate */
val maxTokens: Int?
/** Presence penalty (-2.0 to 2.0) */
val presencePenalty: Double?
/** Stop sequences */
val stop: List<String>?
}Package: com.embabel.common.ai.model
/**
* Spring AI's embedding model interface.
*/
interface EmbeddingModel {
/**
* Embed a single document.
*/
fun embed(document: Document): FloatArray
/**
* Embed multiple text strings.
*/
fun embed(texts: List<String>): MutableList<FloatArray>
/**
* Process an embedding request.
*/
fun call(request: EmbeddingRequest): EmbeddingResponse
}Framework: Spring AI
/**
* Document representation in Spring AI.
*/
class Document(
/** The document content */
val content: String,
/** Document metadata */
val metadata: Map<String, Any> = emptyMap()
) {
/** Unique document identifier */
val id: String
/** Optional embedding vector */
var embedding: FloatArray?
}Framework: Spring AI
/**
* Request for embedding operations.
*/
class EmbeddingRequest(
/** List of texts to embed */
val inputs: List<String>,
/** Optional embedding options */
val options: EmbeddingOptions?
)Framework: Spring AI
/**
* Response from embedding operations.
*/
class EmbeddingResponse(
/** List of embedding results */
val results: List<Embedding>
)Framework: Spring AI
/**
* Individual embedding result.
*/
class Embedding(
/** The embedding vector */
val output: FloatArray,
/** Index in the batch */
val index: Int
)Framework: Spring AI
/**
* Base interface for provider-specific chat options.
*/
interface ChatOptions {
fun getTemperature(): Double?
fun getTopP(): Double?
fun getFrequencyPenalty(): Double?
fun getMaxTokens(): Int?
}Framework: Spring AI
/**
* Chat message interface.
*/
interface Message {
/** Get message content */
String getContent();
/** Get message role (user, assistant, system) */
String getRole();
}Framework: Spring AI
/**
* Mockito interface for configuring stub behavior.
*/
interface OngoingStubbing<T> {
/**
* Return a specific value.
*/
OngoingStubbing<T> thenReturn(T value);
/**
* Throw an exception.
*/
OngoingStubbing<T> thenThrow(Throwable... throwables);
/**
* Provide custom answer logic.
*/
OngoingStubbing<T> thenAnswer(Answer<?> answer);
}Framework: Mockito
/**
* Mockito argument capturing utility.
*/
class ArgumentCaptor<T> {
/**
* Get the last captured value.
*/
T getValue();
/**
* Get all captured values.
*/
List<T> getAllValues();
}Framework: Mockito
/**
* Custom argument matching interface.
*/
@FunctionalInterface
interface ArgumentMatcher<T> {
/**
* Check if argument matches.
*/
boolean matches(T argument);
}Framework: Mockito
/**
* Functional predicate interface.
*/
@FunctionalInterface
interface Predicate<T> {
/**
* Test if value matches predicate.
*/
boolean test(T t);
// Default methods: and, or, negate
}Package: java.util.function
/**
* Utility function to test options converter core value preservation.
* Verifies temperature, topP, and frequencyPenalty are correctly converted.
*
* @param optionsConverter The OptionsConverter to test
* @throws AssertionError if any core values are not preserved
*/
fun checkOptionsConverterPreservesCoreValues(
optionsConverter: OptionsConverter<*>
)Module: embabel-agent-test-internal Package: com.embabel.agent.test.models
Java Usage:
import static com.embabel.agent.test.models.OptionsConverterTestUtilsKt.checkOptionsConverterPreservesCoreValues;
checkOptionsConverterPreservesCoreValues(converter);EmbeddingModel (Spring AI interface)
└── FakeEmbeddingModel (Test implementation)
ChatOptions (Spring AI interface)
├── OpenAiChatOptions
├── AnthropicChatOptions
└── CustomChatOptions
Message (Spring AI interface)
├── UserMessage
├── AssistantMessage
└── SystemMessageEmbabelMockitoIntegrationTest
├── contains: AgentPlatform
└── contains: LlmOperations (mocked)
FakeAiConfiguration
├── provides: LlmService<*> (cheapest)
├── provides: LlmService<*> (best)
└── provides: EmbeddingService
OptionsConverterTestSupport<O>
└── contains: OptionsConverter<O>| Type | Type Parameter | Meaning |
|---|---|---|
OptionsConverter<T> | T extends ChatOptions | Provider-specific options type |
OptionsConverterTestSupport<O> | O extends ChatOptions | Options type being tested |
LlmService<T> | T extends ChatOptions | Options type for this service |
ArgumentCaptor<T> | T | Type of argument to capture |
OngoingStubbing<T> | T | Return type of stubbed method |