Multi-module test support framework for Embabel Agent applications providing integration testing, mock AI services, and test configuration utilities
Understanding how the Embabel Agent Test Support framework is organized and how its components relate to each other.
The test support framework consists of three independent but complementary modules:
embabel-agent-test-support (parent POM)
│
├── embabel-agent-test
│ ├── Purpose: Mockito integration testing
│ ├── Language: Java
│ └── Provides: EmbabelMockitoIntegrationTest
│
├── embabel-agent-test-common
│ ├── Purpose: Fake AI services
│ ├── Language: Kotlin
│ └── Provides: FakeEmbeddingModel
│
└── embabel-agent-test-internal
├── Purpose: Spring test configuration
├── Language: Kotlin
└── Provides: FakeAiConfiguration, OptionsConverterTestSupportembabel-agent-test-internal
├── depends on: embabel-agent-test
├── depends on: embabel-agent-test-common
└── depends on: embabel-agent-domain
embabel-agent-test
└── depends on: embabel-agent-api
embabel-agent-test-common
└── depends on: embabel-agent-commonembabel-agent-test
├── Spring Boot Test
├── Mockito
└── JUnit 5
embabel-agent-test-common
├── Spring AI
└── Kotlin stdlib
embabel-agent-test-internal
├── Spring Boot Test
├── MockK
└── Kotlin stdlibEmbabelMockitoIntegrationTest (abstract base class)
│
├── Annotations
│ ├── @SpringBootTest
│ └── @TestPropertySource
│
├── Injected Components
│ ├── AgentPlatform (autowired)
│ └── LlmOperations (mocked via @MockitoBean)
│
├── Stubbing Methods
│ ├── whenGenerateText(...)
│ └── whenCreateObject(...)
│
├── Verification Methods
│ ├── verifyGenerateText(...)
│ ├── verifyCreateObject(...)
│ ├── verifyNoInteractions()
│ └── verifyNoMoreInteractions()
│
└── Capture Methods
├── capturePrompt()
├── captureLlmInteraction()
└── captureOutputClass()FakeEmbeddingModel
│
├── Implements: EmbeddingModel (Spring AI)
│
├── Properties
│ └── dimensions: Int
│
└── Methods
├── embed(document: Document): FloatArray
├── embed(texts: List<String>): MutableList<FloatArray>
└── call(request: EmbeddingRequest): EmbeddingResponseFakeAiConfiguration
│
├── Annotation: @TestConfiguration
│
└── Beans
├── cheapest(): LlmService<*>
│ └── SpringAiLlmService with mocked ChatModel
├── best(): LlmService<*>
│ └── SpringAiLlmService with mocked ChatModel
└── embedding(): EmbeddingService
└── SpringAiEmbeddingService with FakeEmbeddingModel
OptionsConverterTestSupport<O>
│
├── Type Parameter: O extends ChatOptions
│
├── Properties
│ └── optionsConverter: OptionsConverter<O>
│
└── Tests
└── should preserve core values()Test Code
↓
whenGenerateText(predicate)
↓
Mockito Configuration
↓
LlmOperations Mock
↓
Code Under Test calls LLM
↓
Mock intercepts call
↓
Predicate evaluated
↓
Stubbed response returned
↓
Test Code receives resultTest Code executes
↓
Code Under Test calls LLM
↓
Mockito records interaction
↓
Test Code calls verifyGenerateText(predicate)
↓
Mockito checks recorded interactions
↓
Predicate evaluated against actual calls
↓
Verification passes or fails
↓
Test continues or throws AssertionErrorTest Code
↓
FakeEmbeddingModel.embed(document)
↓
generateRandomFloatArray(dimensions)
↓
Random FloatArray created
↓
Returned to caller
↓
Used in code under testTest Class
↓
@Import(FakeAiConfiguration::class)
↓
Spring Boot Test Context loads
↓
FakeAiConfiguration beans created
├── cheapest bean (mocked LlmService)
├── best bean (mocked LlmService)
└── embedding bean (with FakeEmbeddingModel)
↓
Beans injected into test
↓
Test code uses beansTest Class
│
├── extends EmbabelMockitoIntegrationTest
│ └── provides @SpringBootTest context
│
└── @Import(FakeAiConfiguration::class)
└── adds fake AI beans to context
Result: Full Spring Boot test with mocked LLMs and fake embeddingsEmbabelMockitoIntegrationTest
│
├── @MockitoBean for LlmOperations
│ └── Mockito creates mock
│
└── Helper methods use Mockito API
├── whenGenerateText → Mockito.when()
├── verifyGenerateText → Mockito.verify()
└── capturePrompt → ArgumentCaptorFakeEmbeddingModel implements EmbeddingModel
│
└── Compatible with Spring AI APIs
├── VectorStore
├── EmbeddingClient
└── DocumentTransformer
FakeAiConfiguration provides EmbeddingService
│
└── Uses SpringAiEmbeddingService
└── Wraps FakeEmbeddingModelYour Test Class
├── extends EmbabelMockitoIntegrationTest
├── imports FakeAiConfiguration
└── uses FakeEmbeddingModel directly
Purpose: Write tests for agent applicationsembabel-agent-test-support modules
├── Stubbing/Verification helpers
├── Fake implementations
└── Spring configuration
Purpose: Provide testing infrastructureembabel-agent-api, embabel-agent-common, embabel-agent-domain
├── LlmOperations interface
├── AgentPlatform
└── Domain types
Purpose: Core agent functionalitySpring AI framework
├── EmbeddingModel interface
├── ChatModel interface
└── Spring AI types
Purpose: AI service abstractionsWhat do you need to test?
├── LLM text generation or object creation?
│ └── Use: embabel-agent-test
│ └── Extend EmbabelMockitoIntegrationTest
│
├── Embedding operations?
│ └── Use: embabel-agent-test-common
│ └── Create FakeEmbeddingModel
│
├── Spring components with AI services?
│ └── Use: embabel-agent-test-internal
│ └── @Import(FakeAiConfiguration::class)
│
└── All of the above?
└── Use: All three modules together
├── Extend EmbabelMockitoIntegrationTest
└── @Import(FakeAiConfiguration::class)embabel-agent-test only
│
└── For: Unit/integration tests of agent logic
├── Mock LLM calls
├── Verify interactions
└── No Spring context needed (optional)embabel-agent-test-common only
│
└── For: Embedding pipeline tests
├── Use FakeEmbeddingModel
├── Test storage/retrieval
└── No mocking neededembabel-agent-test-internal only
│
└── For: Spring component tests
├── Inject fake beans
├── Test service integration
└── Full Spring contextAll three modules
│
└── For: Comprehensive agent tests
├── Mock LLM (embabel-agent-test)
├── Fake embeddings (embabel-agent-test-common)
└── Spring context (embabel-agent-test-internal)Each module can be used independently:
Modules work together seamlessly:
Built on standard frameworks:
All modules avoid real API calls:
Optimized for speed:
Extend OptionsConverterTestSupport:
class MyConverterTest : OptionsConverterTestSupport<MyOptions>(
MyOptionsConverter()
) {
// Add custom tests
}Override FakeAiConfiguration beans:
@TestConfiguration
class CustomConfig {
@Bean
@Primary
fun customEmbedding(): EmbeddingService {
// Custom implementation
}
}Create reusable predicates:
public class TestPredicates {
public static final Predicate<String> CONTAINS_ANALYZE =
p -> p.contains("analyze");
public static final Predicate<String> LONG_PROMPT =
p -> p.length() > 100;
}| Operation | Speed | Notes |
|---|---|---|
| Stub setup | Instant | In-memory Mockito configuration |
| LLM mock call | Instant | No network, returns stub |
| Fake embedding | < 1ms | Simple random generation |
| Spring context load | 1-3s | One-time per test class |
| Verification | Instant | Memory lookup |