Repository navigation
Phase 2: Refactor Service Tests to Use Testcontainers #529
Copy link
Copy link
Closed
Description
Overview
Refactor BackfillEmbeddingsServiceTest and SearchContentServiceTest to use Testcontainers with real production code instead of Mockito mocks.
Priority: HIGH
Estimated Time: Week 2
Depends On: #528 (Phase 1)
Context
Replace mock-based testing with integration tests using:
- REAL
ContentPersistenceAdapterandArcadeContentRepository - REAL ArcadeDB with actual vector index
FakeEmbeddingGeneratorfor deterministic embeddings- State-based assertions instead of mock
verify()statements
Benefits
- ✅ Tests validate actual database behavior, not mock interactions
- ✅ Catches SQL errors, schema issues, and mapping bugs
- ✅ Tests survive refactoring (no brittle mock setups)
- ✅ More readable with Given/When/Then structure
- ✅ Validates real vector search with LSM_TREE index
Tasks
2.1 Refactor BackfillEmbeddingsServiceTest
File: src/test/java/it/robfrank/linklift/application/domain/service/BackfillEmbeddingsServiceTest.java
Changes:
- Extend
ArcadeDbTestBaseinstead of using@ExtendWith(MockitoExtension.class) - Replace mocked
LoadContentPortandSaveContentPortwith realrepository - Replace mocked
EmbeddingGeneratorwithFakeEmbeddingGenerator - Update all 11 tests to:
- Use
repository.saveContent()to set up test data - Verify actual database state with
repository.findContentById() - Remove all
verify()statements - Use Awaitility instead of
Thread.sleep()where possible
- Use
Example transformation:
// Before (with mocks)
when(loadContentPort.findContentsWithoutEmbeddings(100))
.thenReturn(List.of(content))
.thenReturn(List.of());
verify(saveContentPort, times(1)).updateContent(argThat(c -> c.embedding() != null));
// After (with Testcontainers)
repository.saveContent(content); // Setup test data in REAL database
backfillEmbeddingsService.backfill();
Thread.sleep(1000);
Content updated = repository.findContentById("id-1").orElseThrow();
assertThat(updated.embedding()).isNotNull().hasSize(384);2.2 Refactor SearchContentServiceTest
File: src/test/java/it/robfrank/linklift/application/domain/service/SearchContentServiceTest.java
Changes:
- Extend
ArcadeDbTestBase - Replace mocked
LoadContentPortwith realrepository - Replace mocked
EmbeddingGeneratorwithFakeEmbeddingGenerator - Update all 21 tests to:
- Save content with embeddings to real database
- Verify actual vector search results using ArcadeDB's LSM_TREE index
- Remove all
verify()statements - Test actual cosine similarity ranking
Example transformation:
// Before (with mocks)
when(embeddingGenerator.generateEmbedding(query)).thenReturn(queryVector);
when(loadContentPort.findSimilar(queryVector, 10)).thenReturn(List.of(resultContent));
// After (with Testcontainers)
Content ml1 = content.withEmbedding(embeddingGenerator.generateEmbedding("machine learning"));
repository.saveContent(ml1);
List<Content> results = searchContentService.search("machine learning basics", 2);
assertThat(results).extracting(Content::id).containsExactlyInAnyOrder("id-1", "id-2");2.3 Update Test Structure
For both test classes:
- Add
@AfterEachto callsuper.tearDownDatabase()and clean upExecutorService - Use Given/When/Then comments for clarity
- Replace
Thread.sleep()with Awaitility where feasible - Ensure all tests use
FIXED_TEST_TIMEfor deterministic dates
2.4 Validation
- All 32 tests pass (11 from BackfillEmbeddings + 21 from SearchContent)
- No Mockito
verify()statements remain in service tests - Tests use real database state assertions
- Measure total execution time (target: under 40 seconds)
- Verify tests catch SQL/schema errors (try intentional typo)
Success Criteria
- Both test classes extend
ArcadeDbTestBase - All mocks replaced with real implementations
- All 32 tests pass with Testcontainers
- Tests validate actual database state
- Execution time under 40 seconds
- Code coverage maintained or improved
Related
- Depends on: Phase 1: Setup Testcontainers Infrastructure for Vector Search Tests #528 (Phase 1)
- See
TEST_REFACTORING_PLAN.mdPhase 2 for examples - Blocks: Phase 3: Optional E2E Tests with Real Ollama (LOW PRIORITY) #530 (Phase 4 - HTTP tests)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
chore(deps-dev): bump qs from 6.14.1 to 6.14.2 in /webapp [skip ci]
chore(deps-dev): bump org.apache.maven.plugins:maven-jar-plugin from …