Multi-module test support framework for Embabel Agent applications providing integration testing, mock AI services, and test configuration utilities
Complete overview of the embabel-agent-test-internal module providing Spring test configuration and utilities.
The embabel-agent-test-internal module provides Spring test configuration classes and utilities for setting up test environments with fake AI services. It includes pre-configured beans for LLM and embedding services, plus utilities for testing options converters.
Module Name: embabel-agent-test-internal Packages:
com.embabel.common.test.ai.config - Test configurationcom.embabel.agent.test.models - Options converter testing utilities
Language: Kotlin (Java-compatible)
Framework: Spring Boot TestAdd to your Maven pom.xml:
<dependency>
<groupId>com.embabel.agent</groupId>
<artifactId>embabel-agent-test-internal</artifactId>
<version>0.3.3</version>
<scope>test</scope>
</dependency>Spring @TestConfiguration providing pre-configured fake AI service beans.
Provides:
cheapest bean - Fake LLM service (gpt-4o-mini)best bean - Fake LLM service (gpt-4o)embedding bean - Fake embedding service (1536 dimensions)Usage:
@SpringBootTest
@Import(FakeAiConfiguration::class)
class MyTest {
@Autowired
private lateinit var cheapest: LlmService<*>
@Autowired
private lateinit var best: LlmService<*>
@Autowired
private lateinit var embeddingService: EmbeddingService
@Test
fun `test with fake services`() {
// Use services without API calls
}
}Abstract base class for testing OptionsConverter implementations.
Features:
Usage:
class MyConverterTest : OptionsConverterTestSupport<MyCustomOptions>(
MyOptionsConverter()
) {
// Inherits core preservation test
@Test
fun `should handle custom parameters`() {
// Add custom tests
}
}Standalone utility function for testing options converters.
Usage:
@Test
fun `test converter`() {
val converter = MyOptionsConverter()
checkOptionsConverterPreservesCoreValues(converter)
}Fake LLM service simulating gpt-4o-mini:
@Autowired
@Qualifier("cheapest")
private lateinit var cheapModel: LlmService<*>
// Or by name
@Autowired
private lateinit var cheapest: LlmService<*>Configuration:
Fake LLM service simulating gpt-4o:
@Autowired
@Qualifier("best")
private lateinit var bestModel: LlmService<*>
// Or by name
@Autowired
private lateinit var best: LlmService<*>Configuration:
Fake embedding service with FakeEmbeddingModel:
@Autowired
private lateinit var embeddingService: EmbeddingServiceConfiguration:
Test that custom converters preserve core LLM values:
Core values tested:
temperature - Controls randomness (0.0 to 2.0)topP - Nucleus sampling parameter (0.0 to 1.0)frequencyPenalty - Token repetition penalty (-2.0 to 2.0)Test services with fake LLM:
@SpringBootTest
@Import(FakeAiConfiguration::class)
class MyServiceTest {
@Autowired
private lateinit var cheapest: LlmService<*>
@Test
fun `test service with fake LLM`() {
val result = myService.process("input", cheapest)
assertNotNull(result)
}
}Test code works with different model tiers:
@Test
fun `feature works with all tiers`() {
// Test with cheap model
val cheapResult = feature.execute(input, cheapest)
// Test with best model
val bestResult = feature.execute(input, best)
assertNotNull(cheapResult)
assertNotNull(bestResult)
}Test code using embeddings:
@Test
fun `test with embeddings`() {
val embedding = embeddingService.embed("test text")
assertEquals(1536, embedding.size)
// Use embedding in your code
}Test custom converters preserve values:
class OpenAiConverterTest : OptionsConverterTestSupport<OpenAiChatOptions>(
OpenAiOptionsConverter()
) {
// Core preservation test inherited
@Test
fun `should convert max tokens`() {
val options = LlmOptions(maxTokens = 1000)
val result = optionsConverter.convert(options)
assertEquals(1000, result.maxTokens)
}
}This module depends on:
All dependencies are transitive.
Use this module when:
✓ Setting up Spring Boot tests with fake AI services ✓ Need pre-configured LLM and embedding beans ✓ Testing code that injects AI services via Spring ✓ Testing model tier selection logic ✓ Testing custom options converters ✓ Want zero-configuration test setup
Don't use this module when:
✗ Not using Spring Boot ✗ Already have custom AI service mocks ✗ Need real AI service behavior ✗ Testing non-Spring components
Combine with embabel-agent-test:
@SpringBootTest
@Import(FakeAiConfiguration::class)
class CombinedTest : EmbabelMockitoIntegrationTest() {
@Autowired
private lateinit var embeddingService: EmbeddingService
@Test
fun `test with stubbing and beans`() {
// Stub LLM
whenGenerateText { it.contains("test") }
.thenReturn("stubbed")
// Use fake embedding
val embedding = embeddingService.embed("test")
// Execute and verify
val result = myAgent.process("test")
verifyGenerateText { it.contains("test") }
assertEquals(1536, embedding.size)
}
}Override specific beans:
@SpringBootTest
@Import(FakeAiConfiguration::class)
class CustomBeanTest {
@TestConfiguration
class CustomConfig {
@Bean
@Primary
fun customEmbedding(): EmbeddingService {
val fakeModel = FakeEmbeddingModel(dimensions = 768)
return SpringAiEmbeddingService(fakeModel, "custom", "Custom")
}
}
@Autowired
private lateinit var embeddingService: EmbeddingService
@Test
fun `test with custom dimensions`() {
val embedding = embeddingService.embed("test")
assertEquals(768, embedding.size)
}
}Use with Spring Boot test slices:
@DataJpaTest
@Import(FakeAiConfiguration::class)
class RepositoryTest {
@Autowired
private lateinit var embeddingService: EmbeddingService
@Test
fun `test with embeddings in repository`() {
val embedding = embeddingService.embed("test")
// Use in repository operations
}
}@SpringBootTest
@Import(FakeAiConfiguration::class)
class DocumentServiceTest {
@Autowired
@Qualifier("cheapest")
private lateinit var cheapModel: LlmService<*>
@Autowired
@Qualifier("best")
private lateinit var bestModel: LlmService<*>
@Autowired
private lateinit var embeddingService: EmbeddingService
@Autowired
private lateinit var documentService: DocumentService
@Test
fun `test document processing with all services`() {
// Service uses cheap model for summaries
val summary = documentService.summarize(document, cheapModel)
assertNotNull(summary)
// Service uses best model for analysis
val analysis = documentService.analyze(document, bestModel)
assertNotNull(analysis)
// Service uses embeddings for search
val embedding = embeddingService.embed(summary)
assertEquals(1536, embedding.size)
// All operations completed without API calls
}
}import com.embabel.agent.test.models.OptionsConverterTestSupport
import org.springframework.ai.openai.OpenAiChatOptions
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals
class OpenAiOptionsConverterTest : OptionsConverterTestSupport<OpenAiChatOptions>(
OpenAiOptionsConverter()
) {
// Core preservation test is automatic
@Test
fun `should convert max tokens`() {
val llmOptions = LlmOptions(maxTokens = 1000)
val result = optionsConverter.convert(llmOptions)
assertEquals(1000, result.maxTokens)
}
@Test
fun `should handle all parameters`() {
val llmOptions = LlmOptions(
temperature = 0.7,
topP = 0.9,
frequencyPenalty = 0.5,
maxTokens = 2000
)
val result = optionsConverter.convert(llmOptions)
assertEquals(0.7, result.temperature)
assertEquals(0.9, result.topP)
assertEquals(0.5, result.frequencyPenalty)
assertEquals(2000, result.maxTokens)
}
}import com.embabel.common.test.ai.config.FakeAiConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.beans.factory.annotation.Autowired;
import org.junit.jupiter.api.Test;
@SpringBootTest
@Import(FakeAiConfiguration.class)
public class MyServiceTest {
@Autowired
private LlmService<?> cheapest;
@Autowired
private LlmService<?> best;
@Autowired
private EmbeddingService embeddingService;
@Test
void testServiceWithFakeAi() {
String result = myService.process("input", cheapest);
assertNotNull(result);
float[] embedding = embeddingService.embed("test");
assertEquals(1536, embedding.length);
}
}| Feature | embabel-agent-test-internal | embabel-agent-test | embabel-agent-test-common |
|---|---|---|---|
| Spring config | ✓ Yes | ✗ No | ✗ No |
| LLM beans | ✓ Yes | ✗ No | ✗ No |
| Embedding beans | ✓ Yes | ✗ No | ✗ No |
| Mockito stubs | ✗ No | ✓ Yes | ✗ No |
| Converter testing | ✓ Yes | ✗ No | ✗ No |
| Language | Kotlin | Java | Kotlin |
See also:
@Import(FakeAiConfiguration::class)@Primary for custom beansOptionsConverterTestSupport