Context
Follow-up to #368. ProviderConfigService has no direct component tests. The service is tested indirectly through OAuthProvidersControllerTests (which mock IProviderConfigService) and AesGcmEncryptionServiceTests (unit tests for the encryption layer), but the actual DB interaction paths are untested.
Scope
Add ProviderConfigServiceTests to MyProject.Component.Tests/Services/ covering:
GetAllAsync: DB records returned with decrypted client IDs, appsettings fallback for unconfigured providers
GetAllAsync: corrupted ciphertext returns null client ID (resilience path)
GetCredentialsAsync: cache miss loads from DB, subsequent call hits cache
GetCredentialsAsync: disabled provider returns null
GetCredentialsAsync: no DB record falls back to appsettings
UpsertAsync: insert new provider config (encrypts and stores)
UpsertAsync: update existing provider config (keeps secret when null)
UpsertAsync: unknown provider returns validation failure
UpsertAsync: cache invalidation after save
UpsertAsync: audit log entry created
Notes
- Uses InMemory EF provider (existing
TestDbContextFactory pattern)
- Needs a real
AesGcmEncryptionService instance (or a test double) since the service encrypts/decrypts
- Mock
HybridCache with NoOpHybridCache (already exists in test fixtures)
Context
Follow-up to #368.
ProviderConfigServicehas no direct component tests. The service is tested indirectly throughOAuthProvidersControllerTests(which mockIProviderConfigService) andAesGcmEncryptionServiceTests(unit tests for the encryption layer), but the actual DB interaction paths are untested.Scope
Add
ProviderConfigServiceTeststoMyProject.Component.Tests/Services/covering:GetAllAsync: DB records returned with decrypted client IDs, appsettings fallback for unconfigured providersGetAllAsync: corrupted ciphertext returns null client ID (resilience path)GetCredentialsAsync: cache miss loads from DB, subsequent call hits cacheGetCredentialsAsync: disabled provider returns nullGetCredentialsAsync: no DB record falls back to appsettingsUpsertAsync: insert new provider config (encrypts and stores)UpsertAsync: update existing provider config (keeps secret when null)UpsertAsync: unknown provider returns validation failureUpsertAsync: cache invalidation after saveUpsertAsync: audit log entry createdNotes
TestDbContextFactorypattern)AesGcmEncryptionServiceinstance (or a test double) since the service encrypts/decryptsHybridCachewithNoOpHybridCache(already exists in test fixtures)