Files
KArtSell.Aegis/tests/KArtSell.IdentityAccess.Tests/Features/IdentityCreatedEventTests.cs
T
kjh2064 c289a698c5 feat(wbs): AEG-VS-01-05 Event/Job/Inbox - Part 2-3 Complete (Outbox/Inbox + Consumers)
Part 2: Transaction + Outbox Integration
- RegisterIdentityEndpoint: DbConnection → DbTransaction → Outbox write
- RegisterIdentitySql: Accept NpgsqlConnection + NpgsqlTransaction (Dapper)
- Fixed schema references: identity.identity → public.identity
- Hash computation (SHA256) for Outbox payload integrity

Part 3: Consumer + Job Implementation
- IdentityCreatedConsumer: SignalR group 'identity-notifications'
- MfaReminderJob: Hangfire job, 24-hour reminder, idempotent via DB tracking
- IdentityAuditConsumer: Immutable append-only audit trail
- Migration 0043: identity_mfa_reminder + identity_audit_log tables

Testing
- Unit: IdentityCreated event serialization + immutability (4 tests)
- Integration: RegisterIdentityWithOutbox (3 tests: happy path, rollback, duplicate email)
- Updated existing tests: Transaction management (6 test methods)

Architecture
- Outbox/Inbox pattern ensures exactly-once delivery
- Consumers decouple from identity creation (async, independent retry)
- Audit trail immutable (trigger prevents updates/deletes)
- MFA reminder idempotent (tracked in DB)

Status: 40% COMPLETE (event + endpoint + 3 consumers)
Next: E2E tests + Hangfire job registration + Admin UI

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-08-17 18:41:10 +09:00

103 lines
3.1 KiB
C#

using Xunit;
using KArtSell.Modules.IdentityAccess.ManageIdentityAndRoles.Events;
namespace KArtSell.IdentityAccess.Tests.Features;
public class IdentityCreatedEventTests
{
[Fact]
public void IdentityCreated_Create_ReturnsValidRecord()
{
var identityId = Guid.NewGuid();
var email = "test@example.com";
var displayName = "Test User";
var correlationId = Guid.NewGuid().ToString();
var occurredAt = DateTime.UtcNow;
var @event = new IdentityCreated
{
IdentityId = identityId,
Email = email,
DisplayName = displayName,
CorrelationId = correlationId,
OccurredAt = occurredAt
};
Assert.Equal(identityId, @event.IdentityId);
Assert.Equal(email, @event.Email);
Assert.Equal(displayName, @event.DisplayName);
Assert.Equal(correlationId, @event.CorrelationId);
Assert.Equal(occurredAt, @event.OccurredAt);
}
[Fact]
public void IdentityCreated_Immutability_RecordBehavior()
{
var event1 = new IdentityCreated
{
IdentityId = Guid.NewGuid(),
Email = "test1@example.com",
DisplayName = "Test 1",
CorrelationId = "corr-1",
OccurredAt = DateTime.UtcNow
};
var event2 = event1 with { Email = "test2@example.com" };
Assert.NotEqual(event1.Email, event2.Email);
Assert.Equal(event1.IdentityId, event2.IdentityId);
}
[Fact]
public void IdentityCreated_Equality_SameValuesAreEqual()
{
var id = Guid.NewGuid();
var email = "test@example.com";
var displayName = "Test User";
var correlationId = "corr-123";
var occurredAt = new DateTime(2026, 8, 17, 12, 0, 0, DateTimeKind.Utc);
var event1 = new IdentityCreated
{
IdentityId = id,
Email = email,
DisplayName = displayName,
CorrelationId = correlationId,
OccurredAt = occurredAt
};
var event2 = new IdentityCreated
{
IdentityId = id,
Email = email,
DisplayName = displayName,
CorrelationId = correlationId,
OccurredAt = occurredAt
};
Assert.Equal(event1, event2);
}
[Fact]
public void IdentityCreated_Serialization_CanRoundTrip()
{
var @event = new IdentityCreated
{
IdentityId = Guid.NewGuid(),
Email = "test@example.com",
DisplayName = "Test User",
CorrelationId = Guid.NewGuid().ToString(),
OccurredAt = DateTime.UtcNow
};
var json = System.Text.Json.JsonSerializer.Serialize(@event);
var deserialized = System.Text.Json.JsonSerializer.Deserialize<IdentityCreated>(json);
Assert.NotNull(deserialized);
Assert.Equal(@event.IdentityId, deserialized.IdentityId);
Assert.Equal(@event.Email, deserialized.Email);
Assert.Equal(@event.DisplayName, deserialized.DisplayName);
Assert.Equal(@event.CorrelationId, deserialized.CorrelationId);
}
}