Files
CBDDC/tests/ZB.MOM.WW.CBDDC.Sample.Console.Tests/SurrealInfrastructureReadinessTests.cs
Joseph Doherty bd10914828
All checks were successful
NuGet Package Publish / nuget (push) Successful in 1m17s
Harden Surreal migration with retry/coverage fixes and XML docs cleanup
2026-02-22 05:39:00 -05:00

99 lines
3.9 KiB
C#

using SurrealDb.Net.Models.Response;
using ZB.MOM.WW.CBDDC.Persistence.Surreal;
namespace ZB.MOM.WW.CBDDC.Sample.Console.Tests;
public class SurrealInfrastructureReadinessTests
{
/// <summary>
/// Verifies schema initialization runs only once for repeated calls.
/// </summary>
[Fact]
public async Task SchemaInitializer_ShouldApplySchemaOnlyOnce()
{
var embeddedClient = Substitute.For<ICBDDCSurrealEmbeddedClient>();
embeddedClient.RawQueryAsync(
Arg.Any<string>(),
Arg.Any<IReadOnlyDictionary<string, object?>>(),
Arg.Any<CancellationToken>())
.Returns(Task.FromResult(default(SurrealDbResponse)!));
var options = new CBDDCSurrealEmbeddedOptions
{
Cdc = new CBDDCSurrealCdcOptions
{
CheckpointTable = "custom_checkpoint",
RetentionDuration = TimeSpan.FromHours(12)
}
};
var initializer = new CBDDCSurrealSchemaInitializer(embeddedClient, options);
await initializer.EnsureInitializedAsync();
await initializer.EnsureInitializedAsync();
await embeddedClient.Received(1).RawQueryAsync(
Arg.Is<string>(sql =>
sql.Contains("DEFINE TABLE OVERWRITE cbddc_oplog_entries", StringComparison.Ordinal) &&
sql.Contains("CHANGEFEED 12h", StringComparison.Ordinal) &&
sql.Contains("DEFINE TABLE OVERWRITE custom_checkpoint", StringComparison.Ordinal)),
Arg.Any<IReadOnlyDictionary<string, object?>>(),
Arg.Any<CancellationToken>());
}
/// <summary>
/// Verifies invalid checkpoint table identifiers are rejected.
/// </summary>
[Fact]
public void SchemaInitializer_WhenCheckpointIdentifierIsInvalid_ThrowsArgumentException()
{
var embeddedClient = Substitute.For<ICBDDCSurrealEmbeddedClient>();
var options = new CBDDCSurrealEmbeddedOptions
{
Cdc = new CBDDCSurrealCdcOptions
{
CheckpointTable = "invalid-checkpoint"
}
};
Should.Throw<ArgumentException>(() => new CBDDCSurrealSchemaInitializer(embeddedClient, options));
}
/// <summary>
/// Verifies readiness returns true when schema init and health checks succeed.
/// </summary>
[Fact]
public async Task ReadinessProbe_WhenSchemaAndHealthSucceed_ReturnsTrue()
{
var embeddedClient = Substitute.For<ICBDDCSurrealEmbeddedClient>();
embeddedClient.HealthAsync(Arg.Any<CancellationToken>()).Returns(true);
var schemaInitializer = Substitute.For<ICBDDCSurrealSchemaInitializer>();
schemaInitializer.EnsureInitializedAsync(Arg.Any<CancellationToken>()).Returns(Task.CompletedTask);
var probe = new CBDDCSurrealReadinessProbe(embeddedClient, schemaInitializer);
bool isReady = await probe.IsReadyAsync();
isReady.ShouldBeTrue();
await schemaInitializer.Received(1).EnsureInitializedAsync(Arg.Any<CancellationToken>());
await embeddedClient.Received(1).HealthAsync(Arg.Any<CancellationToken>());
}
/// <summary>
/// Verifies readiness returns false when schema initialization fails.
/// </summary>
[Fact]
public async Task ReadinessProbe_WhenSchemaInitializationThrows_ReturnsFalse()
{
var embeddedClient = Substitute.For<ICBDDCSurrealEmbeddedClient>();
var schemaInitializer = Substitute.For<ICBDDCSurrealSchemaInitializer>();
schemaInitializer.EnsureInitializedAsync(Arg.Any<CancellationToken>())
.Returns(Task.FromException(new InvalidOperationException("boom")));
var probe = new CBDDCSurrealReadinessProbe(embeddedClient, schemaInitializer);
bool isReady = await probe.IsReadyAsync();
isReady.ShouldBeFalse();
await embeddedClient.DidNotReceive().HealthAsync(Arg.Any<CancellationToken>());
}
}