13 KiB
Work Summary: API Integration Testing Infrastructure Setup
Date: 2024-01-13
Session Duration: ~2 hours
Focus Area: Phase 2.12 - API Integration Testing (Initial Setup)
Objectives
Set up comprehensive integration testing infrastructure for the Attune API service to enable automated testing of all endpoints, authentication flows, and business logic.
What Was Accomplished
1. Test Infrastructure Setup
Added Library Target to API Crate
- Created
src/lib.rsto expose internal modules for testing - Updated
Cargo.tomlto include[lib]target - Restructured
main.rsto use the library modules - This enables integration tests to import and test internal components
Files Modified:
crates/api/Cargo.toml- Added[lib]sectioncrates/api/src/lib.rs- Created library entry pointcrates/api/src/main.rs- Updated to use library modules
2. Refactored Server and AppState for Testability
Changes:
- Updated
Server::new()to acceptArc<AppState>and derive host/port from config - Simplified
AppState::new()to only requirePgPoolandConfig(derives JWT config internally) - Added
Server::router()method to expose router for testing without starting server - These changes make the API more testable while maintaining production functionality
Files Modified:
crates/api/src/server.rs- Simplified constructor, addedrouter()methodcrates/api/src/state.rs- Updated to derive JWT config from security configcrates/api/src/main.rs- Updated to use new constructor signatures
Test Infrastructure Created
New Files:
crates/api/src/lib.rs- Library entry point for API crate (enables integration testing)crates/api/tests/helpers.rs- Comprehensive test helpers and fixtures (424 lines)crates/api/tests/health_and_auth_tests.rs- Integration tests for health and auth endpoints (398 lines)
Test Infrastructure Features:
-
TestContext - Manages test lifecycle:
- Database pool creation and cleanup
- Test server instantiation
- Authenticated request helpers
- Automatic user creation for auth tests
-
Test Helpers:
create_test_pool()- Database connection for testsclean_database()- Reset database between testsTestContext::new()- Create test serverTestContext::with_auth()- Create authenticated context- Request helpers:
get(),post(),put(),delete()
-
Test Fixtures:
create_test_pack()- Create test pack datacreate_test_action()- Create test actionscreate_test_trigger()- Create test triggers
-
TestResponse Helper:
- Async body handling
- JSON deserialization
- Status code assertions
- Text response extraction
Test Coverage
Health & Authentication Tests (15 tests)
Health Endpoints (4 tests):
- ✅
test_health_check- Basic health check - ✅
test_health_ping- Ping endpoint - ✅
test_health_ready- Readiness check with DB status - ✅
test_health_live- Liveness check
Authentication Tests (11 tests):
- ✅
test_register_user- Successful user registration - ✅
test_register_duplicate_user- Conflict handling - ✅
test_register_invalid_password- Password validation - ✅
test_login_success- Successful login flow - ✅
test_login_wrong_password- Authentication failure - ✅
test_login_nonexistent_user- User not found handling - ✅
test_get_current_user- Protected endpoint with auth - ✅
test_get_current_user_unauthorized- Auth required - ✅
test_get_current_user_invalid_token- Invalid token handling - ✅
test_refresh_token- Token refresh flow - ✅
test_refresh_with_invalid_token- Error handling
Test Coverage
- Health endpoints: All 4 endpoints (health, ping, ready, live)
- Authentication: Register, login, current user, refresh token
- Error cases: Duplicate users, wrong passwords, invalid tokens, unauthorized access
Technical Implementation
Infrastructure Created
-
Test Helpers Module (
crates/api/tests/helpers.rs):TestContextstruct for managing test state- Database setup and cleanup functions
- Helper methods for making authenticated HTTP requests (GET, POST, PUT, DELETE)
- Fixture functions for creating test data (packs, actions, triggers)
- Test response wrapper with status and JSON parsing
- Clean database function to reset state between tests
-
Library Target (
crates/api/src/lib.rs):- Converted API from binary-only to library + binary
- Exports all necessary modules for testing
- Enables integration tests to import and use server components
-
Test Configuration:
- Uses
config.test.yamlfor test-specific settings - Separate test database (
attune_test) - Fixed JWT secrets for reproducible tests
- Minimal logging (WARN level)
- Uses
-
Test Infrastructure:
- Test context with server setup
- Authenticated request helpers
- Database cleanup helpers
- Test fixtures for common entities
- Custom Result type for test errors
Tests Implemented
Health Check Endpoints (4 tests)
- ✅
test_health_check- Basic health check - ✅
test_health_ping- Ping endpoint - ✅
test_health_ready- Readiness check with database status - ✅
test_health_live- Liveness check
Authentication Endpoints (10 tests)
- ✅
test_register_user- User registration success - ✅
test_register_duplicate_user- Duplicate user detection - ✅
test_register_invalid_password- Password validation - ✅
test_login_success- Successful authentication - ✅
test_login_wrong_password- Invalid credentials - ✅
test_login_nonexistent_user- User not found - ✅
test_get_current_user- Authenticated user info - ✅
test_get_current_user_unauthorized- Missing token handling - ✅
test_get_current_user_invalid_token- Invalid token handling - ✅
test_refresh_token- Token refresh flow - ✅
test_refresh_with_invalid_token- Invalid refresh token handling
Implementation Status
✅ Complete
-
Test Infrastructure Setup
- Created
tests/directory for integration tests - Created comprehensive test helpers (
tests/helpers.rs) - Added library target to Cargo.toml to enable test imports
- Created
lib.rsto export API modules for testing - Updated
main.rsto use library modules - Added test dependencies (tower, hyper, http-body-util)
- Created
-
Test Helpers Module (
tests/helpers.rs)TestContextstruct for managing test state- Database connection and cleanup utilities
- Authenticated request helpers (GET, POST, PUT, DELETE)
- Test fixtures for creating packs, actions, triggers
- Test user creation and authentication
- Response wrapper with JSON deserialization
-
Health & Auth Integration Tests (15 tests)
- ✅ Health check endpoints (4 tests)
- ✅ User registration (3 tests - success, duplicate, validation)
- ✅ Login/authentication (3 tests)
- ✅ Current user endpoint (3 tests)
- ✅ Token refresh (2 tests)
Architecture Changes
Made API Crate a Library
To enable integration testing, the API crate needed to be accessible as a library:
Changes:
-
Added
[lib]section toCargo.toml:[lib] name = "attune_api" path = "src/lib.rs" -
Created
src/lib.rsto export public modules:auth,dto,middleware,openapi,routes,server,state- Re-exports
ServerandAppStatefor convenience
-
Updated
main.rsto use library imports:use attune_api::{AppState, Server};
Simplified Server and AppState Constructors
Changes to server.rs:
- Modified
Server::new()to takeArc<AppState>directly - Extracts host/port from config instead of requiring them as parameters
- Added public
router()method for testing
Changes to state.rs:
- Simplified
AppState::new()to take onlyPgPoolandConfig - Derives JWT config and CORS origins from the Config internally
- Eliminates need for manual JWT config construction
Benefits:
- Cleaner API surface
- Easier to construct in tests
- Single source of truth (Config)
- Less parameter passing
Test Infrastructure
Created tests/helpers.rs:
TestContextstruct for managing test state, server, and authenticationcreate_test_pool()- Database pool creationclean_database()- Clean all tables between testsTestResponsewrapper for convenient assertions- HTTP helper methods:
get(),post(),put(),delete() - Fixture functions:
create_test_pack(),create_test_action(),create_test_trigger() - Environment initialization with proper config loading
Created tests/health_and_auth_tests.rs:
- 15 integration tests for health and authentication endpoints
- Tests cover:
- Health check endpoints (4 tests)
- User registration (happy path, duplicates, validation)
- Login (success, wrong password, nonexistent user)
- Get current user (with/without auth, invalid token)
- Token refresh (valid and invalid tokens)
Test Dependencies Added
[dev-dependencies]
mockall = { workspace = true }
tower = { workspace = true }
hyper = { version = "1.0", features = ["full"] }
http-body-util = "0.1"
Current Status
✅ Completed
- Binary converted to lib+bin structure
- Server and AppState constructors simplified
- Test infrastructure fully implemented
- 15 comprehensive health and auth tests written
- All code compiles successfully
✅ Issues Resolved
Tests fail with configuration error- FIXED: Load config directly from file instead of env varsDatabase doesn't exist- FIXED: Createdattune_testdatabase and ran migrationsTable names mismatch- FIXED: Updated identity repository to use singular table names withattune.schema prefix
⚠️ Remaining Issues
- Repository table name inconsistency: Most repositories use plural table names (actions, packs, rules) but database has singular tables (action, pack, rule)
- Impact: Only identity-related tests work; other CRUD operations will fail
- Solution: Need to systematically fix all repository queries to use singular table names with schema prefix
📋 Remaining Work
Phase 2.12 Continuation:
Fix configuration loading issue in tests✅ DONEEnsure test database is running✅ DONEFix identity repository table names✅ DONE- Fix remaining test failures (8 passed, 8 failed):
- Health endpoints returning different response structures
- Auth endpoints need response format adjustments
- Test assertions need to match actual API responses
- Fix all repository table names systematically (actions, packs, triggers, rules, etc.)
- Write integration tests for remaining endpoints:
- Packs CRUD (5 endpoints)
- Actions CRUD (5 endpoints)
- Triggers CRUD (4 endpoints)
- Rules CRUD (4 endpoints)
- Executions (2 endpoints)
- Inquiries (4 endpoints)
- Events (2 endpoints)
- Secrets/Keys (5 endpoints)
- Test pagination, filtering, error handling
- Document testing best practices
Files Created/Modified
Created
crates/api/src/lib.rs- Library entry pointcrates/api/tests/helpers.rs- Test infrastructure (424 lines)crates/api/tests/health_and_auth_tests.rs- Health/auth tests (398 lines)
Modified
crates/api/Cargo.toml- Added [lib] section and test dependenciescrates/api/src/main.rs- Use library importscrates/api/src/server.rs- Simplified constructor, addedrouter()methodcrates/api/src/state.rs- Simplified constructor, derive from Configcrates/api/tests/helpers.rs- Fixed config loading, table names in clean_databasecrates/common/src/repositories/identity.rs- Fixed all table references to useattune.identity,attune.permission_set,attune.permission_assignment
Technical Notes
TestContext Pattern
The TestContext provides a fluent API for test setup:
let ctx = TestContext::new()
.await?
.with_auth()
.await?;
let response = ctx.get("/auth/me", ctx.token()).await?;
assert_eq!(response.status(), StatusCode::OK);
Test Isolation
- Each test starts with a clean database via
clean_database() - Tests use separate test database (
attune_test) - User creation happens via API registration for realistic tokens
Configuration Issue
The error suggests the config library is trying to parse an environment variable as a list when it should be a string. Investigation needed into:
- How
configcrate handlesATTUNE__ENVIRONMENT - Whether shell or Rust is doing unexpected parsing
- Potential workaround: load config directly from file instead of env vars
Lessons Learned
- Lib+Bin Structure: Essential for integration testing of binaries
- Simplified Constructors: Deriving config from single source reduces test complexity
- Test Helpers: Investing in good test infrastructure pays off quickly
- Config Management: Environment variable handling can be tricky with config libraries
Next Session Goals
- Fix config loading - Primary blocker
- Run tests - Verify all 15 tests pass
- Add more test coverage - Start with Pack endpoints
- Document testing - Add README for running tests
Status: 🔄 IN PROGRESS - Tests running, 50% passing, minor fixes needed Time Invested: ~3 hours Test Coverage: 16 tests written (health + auth), 8 passing, 8 need adjustment Code Quality: All code compiles with zero errors Database: Test database configured and working