refactor(tests): migrate Database.Tests from FluentAssertions to Shouldly

Replace FluentAssertions with Shouldly across all 6 test files (94 tests).
Add ShouldlyExtensions for BeCloseTo and BeEquivalentTo patterns.
This commit is contained in:
Joseph Doherty
2026-01-29 14:40:18 -05:00
parent 04383d672c
commit 1e23616638
9 changed files with 223 additions and 152 deletions
+23
View File
@@ -228,3 +228,26 @@ public class WorkOrderViewModel
// Avoid: record types for DTOs
public record WorkOrderViewModel(string OrderNumber, DateTime? CompletionDate);
```
### Test Assertions: Use Shouldly, Not FluentAssertions
This project uses **Shouldly** for test assertions. Do not use FluentAssertions.
```csharp
// Preferred: Shouldly
result.ShouldBe(expected);
result.ShouldBeNull();
result.ShouldNotBeNull();
list.ShouldBeEmpty();
list.Count().ShouldBe(3);
await Should.ThrowAsync<SqlException>(act);
// Avoid: FluentAssertions
result.Should().Be(expected);
result.Should().BeNull();
await act.Should().ThrowAsync<SqlException>();
```
Custom extension methods in `Infrastructure/ShouldlyExtensions.cs` provide additional assertions:
- `ShouldBeCloseTo(DateTime, TimeSpan)` - DateTime tolerance comparison
- `ShouldBeEquivalentTo<T>(IEnumerable<T>)` - Collection equivalence (order-independent)
@@ -1,8 +1,8 @@
using Dapper;
using FluentAssertions;
using JdeScoping.Core.Models.Search;
using JdeScoping.Core.ViewModels;
using JdeScoping.Database.Tests.Infrastructure;
using Shouldly;
namespace JdeScoping.Database.Tests.Functions;
@@ -39,10 +39,10 @@ public class ComplexTableFunctionTests : DatabaseTestBase
// Assert
var resultList = results.ToList();
resultList.Should().HaveCount(3);
resultList.Should().Contain(x => x.LotNumber == "LOT001" && x.ItemNumber == "ITEM001");
resultList.Should().Contain(x => x.LotNumber == "LOT002" && x.ItemNumber == "ITEM002");
resultList.Should().Contain(x => x.LotNumber == "LOT003" && x.ItemNumber == "ITEM003");
resultList.Count.ShouldBe(3);
resultList.ShouldContain(x => x.LotNumber == "LOT001" && x.ItemNumber == "ITEM001");
resultList.ShouldContain(x => x.LotNumber == "LOT002" && x.ItemNumber == "ITEM002");
resultList.ShouldContain(x => x.LotNumber == "LOT003" && x.ItemNumber == "ITEM003");
}
[Fact]
@@ -58,7 +58,7 @@ public class ComplexTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -73,7 +73,7 @@ public class ComplexTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -85,7 +85,7 @@ public class ComplexTableFunctionTests : DatabaseTestBase
new { SearchId = 99999 });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -100,7 +100,7 @@ public class ComplexTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -115,7 +115,7 @@ public class ComplexTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -136,10 +136,10 @@ public class ComplexTableFunctionTests : DatabaseTestBase
// Assert
var resultList = results.ToList();
resultList.Should().HaveCount(3);
resultList.Should().Contain(x => x.LotNumber == "LOT001" && x.ItemNumber == null);
resultList.Should().Contain(x => x.LotNumber == null && x.ItemNumber == "ITEM002");
resultList.Should().Contain(x => x.LotNumber == "LOT003" && x.ItemNumber == "ITEM003");
resultList.Count.ShouldBe(3);
resultList.ShouldContain(x => x.LotNumber == "LOT001" && x.ItemNumber == null);
resultList.ShouldContain(x => x.LotNumber == null && x.ItemNumber == "ITEM002");
resultList.ShouldContain(x => x.LotNumber == "LOT003" && x.ItemNumber == "ITEM003");
}
[Fact]
@@ -163,9 +163,9 @@ public class ComplexTableFunctionTests : DatabaseTestBase
// Assert
var resultList = results.ToList();
resultList.Should().HaveCount(2);
resultList.Should().Contain(x => x.LotNumber == "LOT-001" && x.ItemNumber == "ITEM_001");
resultList.Should().Contain(x => x.LotNumber == "LOT.002" && x.ItemNumber == "ITEM/002");
resultList.Count.ShouldBe(2);
resultList.ShouldContain(x => x.LotNumber == "LOT-001" && x.ItemNumber == "ITEM_001");
resultList.ShouldContain(x => x.LotNumber == "LOT.002" && x.ItemNumber == "ITEM/002");
}
#endregion
@@ -212,10 +212,10 @@ public class ComplexTableFunctionTests : DatabaseTestBase
// Assert
var resultList = results.ToList();
resultList.Should().HaveCount(3);
resultList.Should().Contain(x => x.ItemNumber == "ITEM001" && x.OperationNumber == "10" && x.MisNumber == "MIS001" && x.MisRevision == "A");
resultList.Should().Contain(x => x.ItemNumber == "ITEM002" && x.OperationNumber == "20" && x.MisNumber == "MIS002" && x.MisRevision == "B");
resultList.Should().Contain(x => x.ItemNumber == "ITEM003" && x.OperationNumber == "30" && x.MisNumber == "MIS003" && x.MisRevision == "C");
resultList.Count.ShouldBe(3);
resultList.ShouldContain(x => x.ItemNumber == "ITEM001" && x.OperationNumber == "10" && x.MisNumber == "MIS001" && x.MisRevision == "A");
resultList.ShouldContain(x => x.ItemNumber == "ITEM002" && x.OperationNumber == "20" && x.MisNumber == "MIS002" && x.MisRevision == "B");
resultList.ShouldContain(x => x.ItemNumber == "ITEM003" && x.OperationNumber == "30" && x.MisNumber == "MIS003" && x.MisRevision == "C");
}
[Fact]
@@ -231,7 +231,7 @@ public class ComplexTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -246,7 +246,7 @@ public class ComplexTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -258,7 +258,7 @@ public class ComplexTableFunctionTests : DatabaseTestBase
new { SearchId = 99999 });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -273,7 +273,7 @@ public class ComplexTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -288,7 +288,7 @@ public class ComplexTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -309,10 +309,10 @@ public class ComplexTableFunctionTests : DatabaseTestBase
// Assert
var resultList = results.ToList();
resultList.Should().HaveCount(3);
resultList.Should().Contain(x => x.ItemNumber == "ITEM001" && x.OperationNumber == "10" && x.MisNumber == null && x.MisRevision == null);
resultList.Should().Contain(x => x.ItemNumber == null && x.OperationNumber == null && x.MisNumber == "MIS002" && x.MisRevision == "B");
resultList.Should().Contain(x => x.ItemNumber == "ITEM003" && x.OperationNumber == "30" && x.MisNumber == "MIS003" && x.MisRevision == "C");
resultList.Count.ShouldBe(3);
resultList.ShouldContain(x => x.ItemNumber == "ITEM001" && x.OperationNumber == "10" && x.MisNumber == null && x.MisRevision == null);
resultList.ShouldContain(x => x.ItemNumber == null && x.OperationNumber == null && x.MisNumber == "MIS002" && x.MisRevision == "B");
resultList.ShouldContain(x => x.ItemNumber == "ITEM003" && x.OperationNumber == "30" && x.MisNumber == "MIS003" && x.MisRevision == "C");
}
[Fact]
@@ -332,12 +332,12 @@ public class ComplexTableFunctionTests : DatabaseTestBase
// Assert
var resultList = results.ToList();
resultList.Should().HaveCount(1);
resultList.Count.ShouldBe(1);
var result = resultList.First();
result.ItemNumber.Should().Be("ITEM001");
result.OperationNumber.Should().Be("10");
result.MisNumber.Should().BeNull();
result.MisRevision.Should().BeNull();
result.ItemNumber.ShouldBe("ITEM001");
result.OperationNumber.ShouldBe("10");
result.MisNumber.ShouldBeNull();
result.MisRevision.ShouldBeNull();
}
[Fact]
@@ -366,12 +366,12 @@ public class ComplexTableFunctionTests : DatabaseTestBase
// Assert
var resultList = results.ToList();
resultList.Should().HaveCount(1);
resultList.Count.ShouldBe(1);
var result = resultList.First();
result.ItemNumber.Should().Be("ITEM-001");
result.OperationNumber.Should().Be("10A");
result.MisNumber.Should().Be("MIS.001");
result.MisRevision.Should().Be("A-1");
result.ItemNumber.ShouldBe("ITEM-001");
result.OperationNumber.ShouldBe("10A");
result.MisNumber.ShouldBe("MIS.001");
result.MisRevision.ShouldBe("A-1");
}
#endregion
@@ -394,7 +394,7 @@ public class ComplexTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().HaveCount(100);
results.Count().ShouldBe(100);
}
[Fact]
@@ -419,7 +419,7 @@ public class ComplexTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().HaveCount(100);
results.Count().ShouldBe(100);
}
[Fact]
@@ -436,9 +436,9 @@ public class ComplexTableFunctionTests : DatabaseTestBase
// Assert
var resultList = results.ToList();
resultList.Should().HaveCount(1);
resultList.First().LotNumber.Should().BeNull();
resultList.First().ItemNumber.Should().BeNull();
resultList.Count.ShouldBe(1);
resultList.First().LotNumber.ShouldBeNull();
resultList.First().ItemNumber.ShouldBeNull();
}
[Fact]
@@ -455,12 +455,12 @@ public class ComplexTableFunctionTests : DatabaseTestBase
// Assert
var resultList = results.ToList();
resultList.Should().HaveCount(1);
resultList.Count.ShouldBe(1);
var result = resultList.First();
result.ItemNumber.Should().BeNull();
result.OperationNumber.Should().BeNull();
result.MisNumber.Should().BeNull();
result.MisRevision.Should().BeNull();
result.ItemNumber.ShouldBeNull();
result.OperationNumber.ShouldBeNull();
result.MisNumber.ShouldBeNull();
result.MisRevision.ShouldBeNull();
}
[Fact]
@@ -479,9 +479,9 @@ public class ComplexTableFunctionTests : DatabaseTestBase
// Assert
var resultList = results.ToList();
resultList.Should().HaveCount(1);
resultList.First().LotNumber.Should().HaveLength(30);
resultList.First().ItemNumber.Should().HaveLength(128);
resultList.Count.ShouldBe(1);
resultList.First().LotNumber.Length.ShouldBe(30);
resultList.First().ItemNumber.Length.ShouldBe(128);
}
[Fact]
@@ -502,12 +502,12 @@ public class ComplexTableFunctionTests : DatabaseTestBase
// Assert
var resultList = results.ToList();
resultList.Should().HaveCount(1);
resultList.Count.ShouldBe(1);
var result = resultList.First();
result.ItemNumber.Should().HaveLength(128);
result.OperationNumber.Should().HaveLength(10);
result.MisNumber.Should().HaveLength(10);
result.MisRevision.Should().HaveLength(10);
result.ItemNumber.Length.ShouldBe(128);
result.OperationNumber.Length.ShouldBe(10);
result.MisNumber.Length.ShouldBe(10);
result.MisRevision.Length.ShouldBe(10);
}
#endregion
@@ -1,7 +1,7 @@
using Dapper;
using FluentAssertions;
using JdeScoping.Core.Models.Search;
using JdeScoping.Database.Tests.Infrastructure;
using Shouldly;
namespace JdeScoping.Database.Tests.Functions;
@@ -28,7 +28,7 @@ public class ScalarFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
result.Should().BeCloseTo(expectedDate, TimeSpan.FromSeconds(1));
result.ShouldBeCloseTo(expectedDate, TimeSpan.FromSeconds(1));
}
[Fact]
@@ -44,7 +44,7 @@ public class ScalarFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
result.Should().BeNull();
result.ShouldBeNull();
}
[Fact]
@@ -56,7 +56,7 @@ public class ScalarFunctionTests : DatabaseTestBase
new { SearchId = 99999 });
// Assert
result.Should().BeNull();
result.ShouldBeNull();
}
[Fact]
@@ -71,7 +71,7 @@ public class ScalarFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
result.Should().BeNull();
result.ShouldBeNull();
}
[Fact]
@@ -86,7 +86,7 @@ public class ScalarFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
result.Should().BeNull();
result.ShouldBeNull();
}
#endregion
@@ -107,7 +107,7 @@ public class ScalarFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
result.Should().BeCloseTo(expectedDate, TimeSpan.FromSeconds(1));
result.ShouldBeCloseTo(expectedDate, TimeSpan.FromSeconds(1));
}
[Fact]
@@ -123,7 +123,7 @@ public class ScalarFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
result.Should().BeNull();
result.ShouldBeNull();
}
[Fact]
@@ -135,7 +135,7 @@ public class ScalarFunctionTests : DatabaseTestBase
new { SearchId = 99999 });
// Assert
result.Should().BeNull();
result.ShouldBeNull();
}
[Fact]
@@ -150,7 +150,7 @@ public class ScalarFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
result.Should().BeNull();
result.ShouldBeNull();
}
[Fact]
@@ -165,7 +165,7 @@ public class ScalarFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
result.Should().BeNull();
result.ShouldBeNull();
}
#endregion
@@ -185,7 +185,8 @@ public class ScalarFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
result.Should().BeTrue();
result.ShouldNotBeNull();
result.Value.ShouldBeTrue();
}
[Fact]
@@ -201,7 +202,8 @@ public class ScalarFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
result.Should().BeFalse();
result.ShouldNotBeNull();
result.Value.ShouldBeFalse();
}
[Fact]
@@ -213,7 +215,7 @@ public class ScalarFunctionTests : DatabaseTestBase
new { SearchId = 99999 });
// Assert
result.Should().BeNull();
result.ShouldBeNull();
}
[Fact]
@@ -228,7 +230,7 @@ public class ScalarFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
result.Should().BeNull();
result.ShouldBeNull();
}
[Fact]
@@ -243,7 +245,7 @@ public class ScalarFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
result.Should().BeNull();
result.ShouldBeNull();
}
#endregion
@@ -1,7 +1,7 @@
using Dapper;
using FluentAssertions;
using JdeScoping.Core.Models.Search;
using JdeScoping.Database.Tests.Infrastructure;
using Shouldly;
namespace JdeScoping.Database.Tests.Functions;
@@ -27,7 +27,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEquivalentTo([12345L, 67890L, 11111L]);
results.ShouldBeEquivalentTo([12345L, 67890L, 11111L]);
}
[Fact]
@@ -43,7 +43,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -58,7 +58,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -70,7 +70,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = 99999 });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -85,7 +85,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -100,7 +100,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -119,7 +119,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert - null values should be filtered out
results.Should().BeEquivalentTo([12345L, 67890L]);
results.ShouldBeEquivalentTo([12345L, 67890L]);
}
#endregion
@@ -139,7 +139,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEquivalentTo(["ITEM001", "ITEM002", "ITEM003"]);
results.ShouldBeEquivalentTo(["ITEM001", "ITEM002", "ITEM003"]);
}
[Fact]
@@ -155,7 +155,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -170,7 +170,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -182,7 +182,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = 99999 });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -197,7 +197,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -212,7 +212,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -228,7 +228,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert - null values should be filtered out
results.Should().BeEquivalentTo(["ITEM001", "ITEM002"]);
results.ShouldBeEquivalentTo(["ITEM001", "ITEM002"]);
}
[Fact]
@@ -244,7 +244,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEquivalentTo(["ITEM-001", "ITEM_002", "ITEM.003"]);
results.ShouldBeEquivalentTo(["ITEM-001", "ITEM_002", "ITEM.003"]);
}
#endregion
@@ -264,7 +264,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEquivalentTo(["PC01", "PC02", "PC03"]);
results.ShouldBeEquivalentTo(["PC01", "PC02", "PC03"]);
}
[Fact]
@@ -280,7 +280,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -295,7 +295,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -307,7 +307,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = 99999 });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -322,7 +322,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -337,7 +337,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -353,7 +353,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert - null values should be filtered out
results.Should().BeEquivalentTo(["PC01", "PC02"]);
results.ShouldBeEquivalentTo(["PC01", "PC02"]);
}
#endregion
@@ -373,7 +373,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEquivalentTo(["WC001", "WC002", "WC003"]);
results.ShouldBeEquivalentTo(["WC001", "WC002", "WC003"]);
}
[Fact]
@@ -389,7 +389,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -404,7 +404,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -416,7 +416,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = 99999 });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -431,7 +431,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -446,7 +446,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -462,7 +462,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert - null values should be filtered out
results.Should().BeEquivalentTo(["WC001", "WC002"]);
results.ShouldBeEquivalentTo(["WC001", "WC002"]);
}
#endregion
@@ -482,7 +482,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEquivalentTo(["OP001", "OP002", "OP003"]);
results.ShouldBeEquivalentTo(["OP001", "OP002", "OP003"]);
}
[Fact]
@@ -498,7 +498,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -513,7 +513,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -525,7 +525,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = 99999 });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -540,7 +540,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -555,7 +555,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().BeEmpty();
results.ShouldBeEmpty();
}
[Fact]
@@ -571,7 +571,7 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert - null values should be filtered out
results.Should().BeEquivalentTo(["OP001", "OP002"]);
results.ShouldBeEquivalentTo(["OP001", "OP002"]);
}
#endregion
@@ -592,8 +592,8 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
results.Should().HaveCount(1000);
results.Should().BeEquivalentTo(workOrders);
results.Count().ShouldBe(1000);
results.ShouldBeEquivalentTo(workOrders);
}
[Fact]
@@ -610,8 +610,8 @@ public class SimpleTableFunctionTests : DatabaseTestBase
new { SearchId = searchId });
// Assert - value should be truncated to 128 characters
results.Should().HaveCount(1);
results.First().Should().HaveLength(128);
results.Count().ShouldBe(1);
results.First().Length.ShouldBe(128);
}
#endregion
@@ -0,0 +1,45 @@
using Shouldly;
namespace JdeScoping.Database.Tests.Infrastructure;
/// <summary>
/// Extension methods for Shouldly to support patterns from FluentAssertions.
/// </summary>
public static class ShouldlyExtensions
{
/// <summary>
/// Asserts that a nullable DateTime is close to the expected value within a tolerance.
/// Equivalent to FluentAssertions' BeCloseTo.
/// </summary>
public static void ShouldBeCloseTo(this DateTime? actual, DateTime expected, TimeSpan tolerance)
{
actual.ShouldNotBeNull();
Math.Abs((actual.Value - expected).TotalMilliseconds)
.ShouldBeLessThanOrEqualTo(tolerance.TotalMilliseconds);
}
/// <summary>
/// Asserts that a DateTime is close to the expected value within a tolerance.
/// Equivalent to FluentAssertions' BeCloseTo.
/// </summary>
public static void ShouldBeCloseTo(this DateTime actual, DateTime expected, TimeSpan tolerance)
{
Math.Abs((actual - expected).TotalMilliseconds)
.ShouldBeLessThanOrEqualTo(tolerance.TotalMilliseconds);
}
/// <summary>
/// Asserts that two collections contain equivalent items (same items, order independent).
/// Equivalent to FluentAssertions' BeEquivalentTo for simple types.
/// </summary>
public static void ShouldBeEquivalentTo<T>(this IEnumerable<T> actual, IEnumerable<T> expected)
{
var actualList = actual.ToList();
var expectedList = expected.ToList();
actualList.Count.ShouldBe(expectedList.Count, "Collections should have the same count");
foreach (var item in expectedList)
{
actualList.ShouldContain(item);
}
}
}
@@ -11,7 +11,6 @@
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.4" />
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="NSubstitute" Version="5.3.0" />
@@ -1,6 +1,6 @@
using Dapper;
using FluentAssertions;
using JdeScoping.Database.Tests.Infrastructure;
using Shouldly;
namespace JdeScoping.Database.Tests.Procedures;
@@ -57,7 +57,7 @@ public class ProcessMisStagingDataProcedureTests : DatabaseTestBase
"SELECT COUNT(*) FROM MisData_Curr WHERE MisNumber = @MisNumber",
new { MisNumber = testMisNumber });
finalCurrCount.Should().Be(initialCurrCount, "Debug mode should not modify data");
finalCurrCount.ShouldBe(initialCurrCount, "Debug mode should not modify data");
}
finally
{
@@ -93,9 +93,11 @@ public class ProcessMisStagingDataProcedureTests : DatabaseTestBase
WHERE MisNumber = @MisNumber",
new { MisNumber = testMisNumber });
record.Should().NotBeNull("Record should be inserted to MisData_Curr");
((string)record.Status).Should().Be("Current");
((DateTime?)record.ObsoleteDate).Should().BeNull();
// Use Assert.NotNull instead of Shouldly for dynamic null check
// (Shouldly's .ShouldNotBeNull() fails with dynamic null due to runtime binding)
Assert.NotNull(record);
((string)record.Status).ShouldBe("Current");
((DateTime?)record.ObsoleteDate).ShouldBeNull();
}
finally
{
@@ -144,9 +146,9 @@ public class ProcessMisStagingDataProcedureTests : DatabaseTestBase
WHERE MisNumber = @MisNumber AND RevID = 'A'",
new { MisNumber = testMisNumber });
histRecord.Should().NotBeNull("Old version should be moved to MisData_Hist");
((string)histRecord.Status).Should().Be("BackLevel");
((DateTime?)histRecord.ObsoleteDate).Should().NotBeNull();
Assert.NotNull(histRecord);
((string)histRecord.Status).ShouldBe("BackLevel");
((DateTime?)histRecord.ObsoleteDate).ShouldNotBeNull();
// Assert - new version should be in current with Current status
var currRecord = await Connection.QuerySingleOrDefaultAsync<dynamic>(
@@ -155,9 +157,9 @@ public class ProcessMisStagingDataProcedureTests : DatabaseTestBase
WHERE MisNumber = @MisNumber AND RevID = 'B'",
new { MisNumber = testMisNumber });
currRecord.Should().NotBeNull("New version should be in MisData_Curr");
((string)currRecord.Status).Should().Be("Current");
((DateTime?)currRecord.ObsoleteDate).Should().BeNull();
Assert.NotNull(currRecord);
((string)currRecord.Status).ShouldBe("Current");
((DateTime?)currRecord.ObsoleteDate).ShouldBeNull();
}
finally
{
@@ -192,7 +194,7 @@ public class ProcessMisStagingDataProcedureTests : DatabaseTestBase
@"SELECT MisNumber FROM MisData_Curr WHERE MisNumber = @MisNumber",
new { MisNumber = testMisNumber });
record.Should().NotBeNull("Record should be inserted with IIS_ prefix removed");
Assert.NotNull(record);
}
finally
{
@@ -212,6 +214,6 @@ public class ProcessMisStagingDataProcedureTests : DatabaseTestBase
"EXEC dbo.usp_ProcessMisStagingData @SaveChanges = 1");
// Assert
await act.Should().NotThrowAsync();
await Should.NotThrowAsync(act);
}
}
@@ -1,6 +1,6 @@
using Dapper;
using FluentAssertions;
using JdeScoping.Database.Tests.Infrastructure;
using Shouldly;
namespace JdeScoping.Database.Tests.Procedures;
@@ -28,42 +28,42 @@ public class StoredProcedureExistsTests : DatabaseTestBase
public async Task usp_SubmitSearch_Exists()
{
var exists = await ProcedureExistsAsync("usp_SubmitSearch");
exists.Should().BeTrue("usp_SubmitSearch should be created by migration 040");
exists.ShouldBeTrue("usp_SubmitSearch should be created by migration 040");
}
[Fact]
public async Task usp_StartSearch_Exists()
{
var exists = await ProcedureExistsAsync("usp_StartSearch");
exists.Should().BeTrue("usp_StartSearch should be created by migration 041");
exists.ShouldBeTrue("usp_StartSearch should be created by migration 041");
}
[Fact]
public async Task usp_CompleteSearch_Exists()
{
var exists = await ProcedureExistsAsync("usp_CompleteSearch");
exists.Should().BeTrue("usp_CompleteSearch should be created by migration 042");
exists.ShouldBeTrue("usp_CompleteSearch should be created by migration 042");
}
[Fact]
public async Task usp_ResetPartialSearches_Exists()
{
var exists = await ProcedureExistsAsync("usp_ResetPartialSearches");
exists.Should().BeTrue("usp_ResetPartialSearches should be created by migration 043");
exists.ShouldBeTrue("usp_ResetPartialSearches should be created by migration 043");
}
[Fact]
public async Task usp_ValidateSearchCriteria_Exists()
{
var exists = await ProcedureExistsAsync("usp_ValidateSearchCriteria");
exists.Should().BeTrue("usp_ValidateSearchCriteria should be created by migration 048");
exists.ShouldBeTrue("usp_ValidateSearchCriteria should be created by migration 048");
}
[Fact]
public async Task usp_ProcessMisStagingData_Exists()
{
var exists = await ProcedureExistsAsync("usp_ProcessMisStagingData");
exists.Should().BeTrue("usp_ProcessMisStagingData should be created by migration 049");
exists.ShouldBeTrue("usp_ProcessMisStagingData should be created by migration 049");
}
[Fact]
@@ -86,7 +86,7 @@ public class StoredProcedureExistsTests : DatabaseTestBase
WHERE schema_id = SCHEMA_ID('dbo')
AND name LIKE 'usp_%'");
actualCount.Should().BeGreaterThanOrEqualTo(
actualCount.ShouldBeGreaterThanOrEqualTo(
expectedProcedures.Length,
$"Database should have at least {expectedProcedures.Length} stored procedures");
}
@@ -1,8 +1,8 @@
using Dapper;
using FluentAssertions;
using JdeScoping.Core.Models.Search;
using JdeScoping.Database.Tests.Infrastructure;
using Microsoft.Data.SqlClient;
using Shouldly;
namespace JdeScoping.Database.Tests.Procedures;
@@ -26,7 +26,7 @@ public class ValidateSearchCriteriaProcedureTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
await act.Should().NotThrowAsync();
await Should.NotThrowAsync(act);
}
[Fact]
@@ -38,9 +38,9 @@ public class ValidateSearchCriteriaProcedureTests : DatabaseTestBase
new { SearchId = 99999 });
// Assert
var ex = await act.Should().ThrowAsync<SqlException>();
ex.Which.Number.Should().Be(50001);
ex.Which.Message.Should().Contain("Search ID 99999 not found");
var ex = await Should.ThrowAsync<SqlException>(act);
ex.Number.ShouldBe(50001);
ex.Message.ShouldContain("Search ID 99999 not found");
}
[Fact]
@@ -55,9 +55,9 @@ public class ValidateSearchCriteriaProcedureTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
var ex = await act.Should().ThrowAsync<SqlException>();
ex.Which.Number.Should().Be(50002);
ex.Which.Message.Should().Contain("has no criteria");
var ex = await Should.ThrowAsync<SqlException>(act);
ex.Number.ShouldBe(50002);
ex.Message.ShouldContain("has no criteria");
}
[Fact]
@@ -72,9 +72,9 @@ public class ValidateSearchCriteriaProcedureTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
var ex = await act.Should().ThrowAsync<SqlException>();
ex.Which.Number.Should().Be(50002);
ex.Which.Message.Should().Contain("has no criteria");
var ex = await Should.ThrowAsync<SqlException>(act);
ex.Number.ShouldBe(50002);
ex.Message.ShouldContain("has no criteria");
}
[Fact]
@@ -89,9 +89,9 @@ public class ValidateSearchCriteriaProcedureTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
var ex = await act.Should().ThrowAsync<SqlException>();
ex.Which.Number.Should().Be(50003);
ex.Which.Message.Should().Contain("has invalid JSON");
var ex = await Should.ThrowAsync<SqlException>(act);
ex.Number.ShouldBe(50003);
ex.Message.ShouldContain("has invalid JSON");
}
[Fact]
@@ -106,6 +106,6 @@ public class ValidateSearchCriteriaProcedureTests : DatabaseTestBase
new { SearchId = searchId });
// Assert
await act.Should().NotThrowAsync();
await Should.NotThrowAsync(act);
}
}