diff --git a/tests/SIGCM2.Api.Tests/Audit/TransactionScopeSpikeTests.cs b/tests/SIGCM2.Api.Tests/Audit/TransactionScopeSpikeTests.cs new file mode 100644 index 0000000..32c9ca3 --- /dev/null +++ b/tests/SIGCM2.Api.Tests/Audit/TransactionScopeSpikeTests.cs @@ -0,0 +1,58 @@ +using System.Transactions; +using FluentAssertions; +using Microsoft.Data.SqlClient; +using Xunit; + +namespace SIGCM2.Api.Tests.Audit; + +/// UDT-010 Batch 0 — anti-MSDTC spike. Validates design decision #D-1: +/// TransactionScope with AsyncFlowEnabled must NOT escalate to MSDTC when +/// multiple SqlConnections share a single connection string. If this fails, +/// UDT-010 must pivot to explicit IUnitOfWork. +public sealed class TransactionScopeSpikeTests +{ + private const string ConnectionString = + "Server=TECNICA3;Database=SIGCM2_Test;User Id=desarrollo;Password=desarrollo2026;TrustServerCertificate=True;"; + + [Fact] + public async Task TransactionScope_DoesNotEscalateToMSDTC_WithSingleConnectionString() + { + var txOptions = new TransactionOptions + { + IsolationLevel = IsolationLevel.ReadCommitted + }; + + using var tx = new TransactionScope( + TransactionScopeOption.Required, + txOptions, + TransactionScopeAsyncFlowOption.Enabled); + + await using (var conn1 = new SqlConnection(ConnectionString)) + { + await conn1.OpenAsync(); + using var cmd1 = conn1.CreateCommand(); + cmd1.CommandText = "SELECT 1"; + var result1 = await cmd1.ExecuteScalarAsync(); + result1.Should().Be(1); + } + + await using (var conn2 = new SqlConnection(ConnectionString)) + { + await conn2.OpenAsync(); + using var cmd2 = conn2.CreateCommand(); + cmd2.CommandText = "SELECT 1"; + var result2 = await cmd2.ExecuteScalarAsync(); + result2.Should().Be(1); + } + + var current = Transaction.Current; + current.Should().NotBeNull("TransactionScope must set an ambient transaction"); + current!.TransactionInformation.DistributedIdentifier + .Should().Be(Guid.Empty, + "SQL Server with a single connection string must NOT escalate to MSDTC. " + + "If this assertion fails, UDT-010 design must pivot to explicit IUnitOfWork " + + "(see sdd/udt-010-auditoria-trazabilidad/design #D-1)."); + + tx.Complete(); + } +}