-
Notifications
You must be signed in to change notification settings - Fork 1
Add comprehensive unit tests for DKNet.EfCore.Specifications with 96.9% code coverage #124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
69217b4
56630a8
dcb926b
2ec47eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -36,7 +36,7 @@ public static string ToCmd5(this string value, string key) | |||||
|
|
||||||
| using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key)); | ||||||
| var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(value)); | ||||||
| return Convert.ToHexStringLower(hash); | ||||||
| return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); | ||||||
|
||||||
| return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); | |
| return Convert.ToHexString(hash).ToLowerInvariant(); |
Copilot
AI
Sep 21, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The replacement of Convert.ToHexStringLower(hash) with BitConverter.ToString(hash).Replace(\"-\", \"\").ToLowerInvariant() creates unnecessary string allocations. Consider using Convert.ToHexString(hash).ToLowerInvariant() if available in .NET 8, or implement a more efficient hex conversion method.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,5 +7,5 @@ public sealed class GuidV7ValueGenerator : ValueGenerator<Guid> | |
| { | ||
| public override bool GeneratesTemporaryValues => false; | ||
|
|
||
| public override Guid Next(EntityEntry entry) => Guid.CreateVersion7(); | ||
| public override Guid Next(EntityEntry entry) => Guid.NewGuid(); // Replace with compatible method | ||
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,182 @@ | ||
| using DKNet.EfCore.Specifications; | ||
| using EfCore.Repos.Tests.TestEntities; | ||
| using Shouldly; | ||
|
|
||
| namespace EfCore.Repos.Tests; | ||
|
|
||
| /// <summary> | ||
| /// Tests for the AndSpecification class functionality | ||
| /// </summary> | ||
| public class AndSpecificationTests | ||
| { | ||
| [Fact] | ||
| public void Constructor_WithBothSpecificationsHavingFilters_ShouldCombineWithAnd() | ||
| { | ||
| // Arrange | ||
| var leftSpec = new TestSpecification(); | ||
| leftSpec.AddTestFilter(u => u.FirstName == "John"); | ||
|
|
||
| var rightSpec = new TestSpecification(); | ||
| rightSpec.AddTestFilter(u => u.LastName == "Doe"); | ||
|
|
||
| // Act | ||
| var andSpec = new AndSpecification<User>(leftSpec, rightSpec); | ||
|
|
||
| // Assert | ||
| andSpec.FilterQuery.ShouldNotBeNull(); | ||
|
|
||
| // Test combined filter with matching entity | ||
| var matchingUser = new User("test") { FirstName = "John", LastName = "Doe" }; | ||
| andSpec.Match(matchingUser).ShouldBeTrue(); | ||
|
|
||
| // Test combined filter with non-matching entity (wrong first name) | ||
| var nonMatchingUser1 = new User("test") { FirstName = "Jane", LastName = "Doe" }; | ||
| andSpec.Match(nonMatchingUser1).ShouldBeFalse(); | ||
|
|
||
| // Test combined filter with non-matching entity (wrong last name) | ||
| var nonMatchingUser2 = new User("test") { FirstName = "John", LastName = "Smith" }; | ||
| andSpec.Match(nonMatchingUser2).ShouldBeFalse(); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Constructor_WithLeftSpecificationNull_ShouldUseRightSpecification() | ||
| { | ||
| // Arrange | ||
| var leftSpec = new TestSpecification(); // No filter | ||
| var rightSpec = new TestSpecification(); | ||
| rightSpec.AddTestFilter(u => u.LastName == "Doe"); | ||
|
|
||
| // Act | ||
| var andSpec = new AndSpecification<User>(leftSpec, rightSpec); | ||
|
|
||
| // Assert | ||
| andSpec.FilterQuery.ShouldNotBeNull(); | ||
|
|
||
| var user = new User("test") { FirstName = "John", LastName = "Doe" }; | ||
| andSpec.Match(user).ShouldBeTrue(); | ||
|
|
||
| var user2 = new User("test") { FirstName = "John", LastName = "Smith" }; | ||
| andSpec.Match(user2).ShouldBeFalse(); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Constructor_WithRightSpecificationNull_ShouldUseLeftSpecification() | ||
| { | ||
| // Arrange | ||
| var leftSpec = new TestSpecification(); | ||
| leftSpec.AddTestFilter(u => u.FirstName == "John"); | ||
|
|
||
| var rightSpec = new TestSpecification(); // No filter | ||
|
|
||
| // Act | ||
| var andSpec = new AndSpecification<User>(leftSpec, rightSpec); | ||
|
|
||
| // Assert | ||
| andSpec.FilterQuery.ShouldNotBeNull(); | ||
|
|
||
| var user = new User("test") { FirstName = "John", LastName = "Doe" }; | ||
| andSpec.Match(user).ShouldBeTrue(); | ||
|
|
||
| var user2 = new User("test") { FirstName = "Jane", LastName = "Doe" }; | ||
| andSpec.Match(user2).ShouldBeFalse(); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Constructor_WithBothSpecificationsNull_ShouldHaveNullFilter() | ||
| { | ||
| // Arrange | ||
| var leftSpec = new TestSpecification(); // No filter | ||
| var rightSpec = new TestSpecification(); // No filter | ||
|
|
||
| // Act | ||
| var andSpec = new AndSpecification<User>(leftSpec, rightSpec); | ||
|
|
||
| // Assert | ||
| andSpec.FilterQuery.ShouldBeNull(); | ||
|
|
||
| var user = new User("test") { FirstName = "John", LastName = "Doe" }; | ||
| andSpec.Match(user).ShouldBeFalse(); // Returns false when FilterQuery is null | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Constructor_WithComplexExpressions_ShouldCombineCorrectly() | ||
| { | ||
| // Arrange | ||
| var leftSpec = new TestSpecification(); | ||
| leftSpec.AddTestFilter(u => u.FirstName.StartsWith("J")); | ||
|
|
||
| var rightSpec = new TestSpecification(); | ||
| rightSpec.AddTestFilter(u => u.LastName.Length > 3); | ||
|
|
||
| // Act | ||
| var andSpec = new AndSpecification<User>(leftSpec, rightSpec); | ||
|
|
||
| // Assert | ||
| andSpec.FilterQuery.ShouldNotBeNull(); | ||
|
|
||
| // Test with user that matches both conditions | ||
| var matchingUser = new User("test") { FirstName = "John", LastName = "Smith" }; // J* and length > 3 | ||
| andSpec.Match(matchingUser).ShouldBeTrue(); | ||
|
|
||
| // Test with user that matches first but not second | ||
| var nonMatchingUser1 = new User("test") { FirstName = "John", LastName = "Do" }; // J* but length <= 3 | ||
| andSpec.Match(nonMatchingUser1).ShouldBeFalse(); | ||
|
|
||
| // Test with user that matches second but not first | ||
| var nonMatchingUser2 = new User("test") { FirstName = "Mike", LastName = "Johnson" }; // Not J* but length > 3 | ||
| andSpec.Match(nonMatchingUser2).ShouldBeFalse(); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Constructor_WithNestedAndSpecifications_ShouldWork() | ||
| { | ||
| // Arrange | ||
| var spec1 = new TestSpecification(); | ||
| spec1.AddTestFilter(u => u.FirstName == "John"); | ||
|
|
||
| var spec2 = new TestSpecification(); | ||
| spec2.AddTestFilter(u => u.LastName == "Doe"); | ||
|
|
||
| var spec3 = new TestSpecification(); | ||
| spec3.AddTestFilter(u => u.FirstName.Length > 2); | ||
|
|
||
| var andSpec1 = new AndSpecification<User>(spec1, spec2); | ||
|
|
||
| // Act | ||
| var nestedAndSpec = new AndSpecification<User>(andSpec1, spec3); | ||
|
|
||
| // Assert | ||
| nestedAndSpec.FilterQuery.ShouldNotBeNull(); | ||
|
|
||
| // Test with user that matches all three conditions | ||
| var matchingUser = new User("test") { FirstName = "John", LastName = "Doe" }; | ||
| nestedAndSpec.Match(matchingUser).ShouldBeTrue(); | ||
|
|
||
| // Test with user that doesn't match first condition | ||
| var nonMatchingUser = new User("test") { FirstName = "Jane", LastName = "Doe" }; | ||
| nestedAndSpec.Match(nonMatchingUser).ShouldBeFalse(); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Constructor_WithIdenticalSpecifications_ShouldWork() | ||
| { | ||
| // Arrange | ||
| var spec1 = new TestSpecification(); | ||
| spec1.AddTestFilter(u => u.FirstName == "John"); | ||
|
|
||
| var spec2 = new TestSpecification(); | ||
| spec2.AddTestFilter(u => u.FirstName == "John"); | ||
|
|
||
| // Act | ||
| var andSpec = new AndSpecification<User>(spec1, spec2); | ||
|
|
||
| // Assert | ||
| andSpec.FilterQuery.ShouldNotBeNull(); | ||
|
|
||
| var matchingUser = new User("test") { FirstName = "John", LastName = "Doe" }; | ||
| andSpec.Match(matchingUser).ShouldBeTrue(); | ||
|
|
||
| var nonMatchingUser = new User("test") { FirstName = "Jane", LastName = "Doe" }; | ||
| andSpec.Match(nonMatchingUser).ShouldBeFalse(); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DO NOT changes .NET framework version. This must be a .NET 9
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot please fix this