Skip to content

Commit 2602bec

Browse files
committed
feat: Add unit tests for Azure.KeyVault health check
1 parent 54366a7 commit 2602bec

File tree

8 files changed

+491
-1
lines changed

8 files changed

+491
-1
lines changed

Directory.Packages.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<PackageVersion Include="Azure.Security.KeyVault.Secrets" Version="4.8.0" />
3131
<PackageVersion Include="Azure.Storage.Blobs" Version="12.25.1" />
3232
<PackageVersion Include="Azure.Storage.Queues" Version="12.23.0" />
33-
<PackageVersion Include="AzureKeyVaultEmulator.TestContainers" Version="0.6.0" />
33+
<PackageVersion Include="AzureKeyVaultEmulator.TestContainers" Version="2.3.3" />
3434
<PackageVersion Include="ClickHouse.Client" Version="7.14.0" />
3535
<PackageVersion Include="CliWrap" Version="3.9.0" />
3636
<PackageVersion Include="Confluent.Kafka" Version="2.11.1" />
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
namespace NetEvolve.HealthChecks.Tests.Integration.Azure.KeyVault;
2+
3+
using System;
4+
using System.Threading.Tasks;
5+
using AzureKeyVaultEmulator.TestContainers;
6+
using global::Azure.Identity;
7+
using global::Azure.Security.KeyVault.Secrets;
8+
9+
public sealed class AzureKeyVaultAccess : IAsyncInitializer, IAsyncDisposable
10+
{
11+
private readonly AzureKeyVaultEmulatorContainer _container = new AzureKeyVaultEmulatorContainerBuilder().Build();
12+
13+
public Uri VaultUri { get; private set; } = default!;
14+
15+
public string ConnectionString => VaultUri?.ToString() ?? string.Empty;
16+
17+
public async ValueTask DisposeAsync() => await _container.DisposeAsync().ConfigureAwait(false);
18+
19+
public async Task InitializeAsync()
20+
{
21+
await _container.StartAsync().ConfigureAwait(false);
22+
23+
VaultUri = new Uri(_container.GetVaultUri());
24+
25+
await PrepareKeyVaultRequirements().ConfigureAwait(false);
26+
}
27+
28+
private async Task PrepareKeyVaultRequirements()
29+
{
30+
var secretClient = new SecretClient(VaultUri, new DefaultAzureCredential());
31+
32+
// Create a test secret
33+
_ = await secretClient.SetSecretAsync("test-secret", "test-value").ConfigureAwait(false);
34+
}
35+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
namespace NetEvolve.HealthChecks.Tests.Integration.Azure.KeyVault;
2+
3+
using System.Threading.Tasks;
4+
using Microsoft.Extensions.Azure;
5+
using Microsoft.Extensions.Diagnostics.HealthChecks;
6+
using NetEvolve.Extensions.TUnit;
7+
using NetEvolve.HealthChecks.Azure.KeyVault;
8+
9+
[TestGroup($"{nameof(Azure)}.{nameof(KeyVault)}")]
10+
[ClassDataSource<AzureKeyVaultAccess>(Shared = InstanceSharedType.Azure)]
11+
public class KeyVaultSecretAvailableHealthCheckTests : HealthCheckTestBase
12+
{
13+
private readonly AzureKeyVaultAccess _container;
14+
15+
public KeyVaultSecretAvailableHealthCheckTests(AzureKeyVaultAccess container) => _container = container;
16+
17+
[Test]
18+
public async Task AddKeyVaultSecretAvailability_UseOptions_ModeServiceProvider_Healthy() =>
19+
await RunAndVerify(
20+
healthChecks =>
21+
{
22+
_ = healthChecks.AddKeyVaultSecretAvailability(
23+
"ServiceProviderHealthy",
24+
options =>
25+
{
26+
options.Mode = KeyVaultClientCreationMode.ServiceProvider;
27+
options.Timeout = 10000; // Set a reasonable timeout
28+
}
29+
);
30+
},
31+
HealthStatus.Healthy,
32+
serviceBuilder: services =>
33+
services.AddAzureClients(clients => _ = clients.AddSecretClient(_container.VaultUri))
34+
);
35+
36+
[Test]
37+
public async Task AddKeyVaultSecretAvailability_UseOptions_ModeServiceProvider_Degraded() =>
38+
await RunAndVerify(
39+
healthChecks =>
40+
{
41+
_ = healthChecks.AddKeyVaultSecretAvailability(
42+
"ServiceProviderDegraded",
43+
options =>
44+
{
45+
options.Mode = KeyVaultClientCreationMode.ServiceProvider;
46+
options.Timeout = 0;
47+
}
48+
);
49+
},
50+
HealthStatus.Degraded,
51+
serviceBuilder: services =>
52+
services.AddAzureClients(clients => _ = clients.AddSecretClient(_container.VaultUri))
53+
);
54+
55+
[Test]
56+
public async Task AddKeyVaultSecretAvailability_UseOptions_ModeDefaultAzureCredentials_Healthy() =>
57+
await RunAndVerify(
58+
healthChecks =>
59+
{
60+
_ = healthChecks.AddKeyVaultSecretAvailability(
61+
"DefaultAzureCredentialsHealthy",
62+
options =>
63+
{
64+
options.Mode = KeyVaultClientCreationMode.DefaultAzureCredentials;
65+
options.VaultUri = _container.VaultUri;
66+
options.Timeout = 10000; // Set a reasonable timeout
67+
}
68+
);
69+
},
70+
HealthStatus.Healthy
71+
);
72+
73+
[Test]
74+
public async Task AddKeyVaultSecretAvailability_UseOptions_ModeDefaultAzureCredentials_Degraded() =>
75+
await RunAndVerify(
76+
healthChecks =>
77+
{
78+
_ = healthChecks.AddKeyVaultSecretAvailability(
79+
"DefaultAzureCredentialsDegraded",
80+
options =>
81+
{
82+
options.Mode = KeyVaultClientCreationMode.DefaultAzureCredentials;
83+
options.VaultUri = _container.VaultUri;
84+
options.Timeout = 0;
85+
}
86+
);
87+
},
88+
HealthStatus.Degraded
89+
);
90+
91+
[Test]
92+
public async Task AddKeyVaultSecretAvailability_UseOptions_ModeManagedIdentity_Healthy() =>
93+
await RunAndVerify(
94+
healthChecks =>
95+
{
96+
_ = healthChecks.AddKeyVaultSecretAvailability(
97+
"ManagedIdentityHealthy",
98+
options =>
99+
{
100+
options.Mode = KeyVaultClientCreationMode.ManagedIdentity;
101+
options.VaultUri = _container.VaultUri;
102+
options.Timeout = 10000; // Set a reasonable timeout
103+
}
104+
);
105+
},
106+
HealthStatus.Healthy
107+
);
108+
109+
[Test]
110+
public async Task AddKeyVaultSecretAvailability_UseOptions_ModeManagedIdentity_Degraded() =>
111+
await RunAndVerify(
112+
healthChecks =>
113+
{
114+
_ = healthChecks.AddKeyVaultSecretAvailability(
115+
"ManagedIdentityDegraded",
116+
options =>
117+
{
118+
options.Mode = KeyVaultClientCreationMode.ManagedIdentity;
119+
options.VaultUri = _container.VaultUri;
120+
options.Timeout = 0;
121+
}
122+
);
123+
},
124+
HealthStatus.Degraded
125+
);
126+
}

tests/NetEvolve.HealthChecks.Tests.Integration/NetEvolve.HealthChecks.Tests.Integration.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<PackageReference Include="ArangoDBNetStandard" />
1616
<PackageReference Include="Azure.Data.Tables" />
1717
<PackageReference Include="Azure.Messaging.ServiceBus" />
18+
<PackageReference Include="Azure.Security.KeyVault.Secrets" />
1819
<PackageReference Include="Azure.Storage.Blobs" />
1920
<PackageReference Include="Azure.Storage.Queues" />
2021
<PackageReference Include="ClickHouse.Client" />
@@ -63,6 +64,7 @@
6364
<PackageReference Include="Testcontainers.ActiveMq" />
6465
<PackageReference Include="Testcontainers.ArangoDb" />
6566
<PackageReference Include="Testcontainers.Azurite" />
67+
<PackageReference Include="AzureKeyVaultEmulator.TestContainers" />
6668
<PackageReference Include="Testcontainers.ClickHouse" />
6769
<PackageReference Include="Testcontainers.Consul" />
6870
<PackageReference Include="Testcontainers.Db2" />
@@ -106,6 +108,7 @@
106108
<ProjectReference Include="..\..\src\NetEvolve.HealthChecks.AWS.SQS\NetEvolve.HealthChecks.AWS.SQS.csproj" />
107109
<ProjectReference Include="..\..\src\NetEvolve.HealthChecks.Azure.ApplicationInsights\NetEvolve.HealthChecks.Azure.ApplicationInsights.csproj" />
108110
<ProjectReference Include="..\..\src\NetEvolve.HealthChecks.Azure.Blobs\NetEvolve.HealthChecks.Azure.Blobs.csproj" />
111+
<ProjectReference Include="..\..\src\NetEvolve.HealthChecks.Azure.KeyVault\NetEvolve.HealthChecks.Azure.KeyVault.csproj" />
109112
<ProjectReference Include="..\..\src\NetEvolve.HealthChecks.Azure.Queues\NetEvolve.HealthChecks.Azure.Queues.csproj" />
110113
<ProjectReference Include="..\..\src\NetEvolve.HealthChecks.Azure.ServiceBus\NetEvolve.HealthChecks.Azure.ServiceBus.csproj" />
111114
<ProjectReference Include="..\..\src\NetEvolve.HealthChecks.Azure.Tables\NetEvolve.HealthChecks.Azure.Tables.csproj" />
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
namespace NetEvolve.HealthChecks.Tests.Unit.Azure.KeyVault;
2+
3+
using System;
4+
using Microsoft.Extensions.Configuration;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using NetEvolve.Extensions.TUnit;
7+
using NetEvolve.HealthChecks.Azure.KeyVault;
8+
9+
[TestGroup($"{nameof(Azure)}.{nameof(KeyVault)}")]
10+
public class DependencyInjectionExtensionsTests
11+
{
12+
[Test]
13+
public void AddKeyVaultSecretAvailability_WhenArgumentBuilderNull_ThrowArgumentNullException()
14+
{
15+
// Arrange
16+
var builder = default(IHealthChecksBuilder);
17+
18+
// Act
19+
void Act() => builder.AddKeyVaultSecretAvailability("Test");
20+
21+
// Assert
22+
_ = Assert.Throws<ArgumentNullException>("builder", Act);
23+
}
24+
25+
[Test]
26+
public void AddKeyVaultSecretAvailability_WhenArgumentNameNull_ThrowArgumentNullException()
27+
{
28+
// Arrange
29+
var configuration = new ConfigurationBuilder().Build();
30+
var services = new ServiceCollection();
31+
var builder = services.AddSingleton<IConfiguration>(configuration).AddHealthChecks();
32+
const string? name = default;
33+
34+
// Act
35+
void Act() => builder.AddKeyVaultSecretAvailability(name!);
36+
37+
// Assert
38+
_ = Assert.Throws<ArgumentNullException>("name", Act);
39+
}
40+
41+
[Test]
42+
public void AddKeyVaultSecretAvailability_WhenArgumentNameEmpty_ThrowArgumentException()
43+
{
44+
// Arrange
45+
var configuration = new ConfigurationBuilder().Build();
46+
var services = new ServiceCollection();
47+
var builder = services.AddSingleton<IConfiguration>(configuration).AddHealthChecks();
48+
var name = string.Empty;
49+
50+
// Act
51+
void Act() => builder.AddKeyVaultSecretAvailability(name);
52+
53+
// Assert
54+
_ = Assert.Throws<ArgumentException>("name", Act);
55+
}
56+
57+
[Test]
58+
public void AddKeyVaultSecretAvailability_WhenArgumentTagsNull_ThrowArgumentNullException()
59+
{
60+
// Arrange
61+
var configuration = new ConfigurationBuilder().Build();
62+
var services = new ServiceCollection();
63+
var builder = services.AddSingleton<IConfiguration>(configuration).AddHealthChecks();
64+
var tags = default(string[]);
65+
66+
// Act
67+
void Act() => builder.AddKeyVaultSecretAvailability("Test", tags: tags);
68+
69+
// Assert
70+
_ = Assert.Throws<ArgumentNullException>("tags", Act);
71+
}
72+
73+
[Test]
74+
public void AddKeyVaultSecretAvailability_WhenArgumentNameIsAlreadyUsed_ThrowArgumentException()
75+
{
76+
// Arrange
77+
var configuration = new ConfigurationBuilder().Build();
78+
var services = new ServiceCollection();
79+
var builder = services.AddSingleton<IConfiguration>(configuration).AddHealthChecks();
80+
const string? name = "Test";
81+
82+
// Act
83+
void Act() => builder.AddKeyVaultSecretAvailability(name, __ => { }).AddKeyVaultSecretAvailability(name);
84+
85+
// Assert
86+
_ = Assert.Throws<ArgumentException>(nameof(name), Act);
87+
}
88+
}

0 commit comments

Comments
 (0)