Skip to content

Commit d3cce49

Browse files
author
Akácz Károly
committed
test: achieve 100% line and branch coverage
Add missing tests for validation logic branches: - CreditCard: invalid Luhn checksum test (valid length but wrong checksum) - CustomRule: default error message when null (line 63 null coalescing) - RuleBuilder: null propertyValidator defensive test - ValidationResult.AddError: null error defensive test - Unless: defensive test for missing rule Coverage: 280/280 lines (100%), 184/184 branches (100%)
1 parent af7de0d commit d3cce49

5 files changed

Lines changed: 98 additions & 0 deletions

File tree

tests/Fox.ValidationKit.Tests/CommonValidatorTests.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,18 @@ public void CreditCard_should_fail_for_null()
165165
result.Errors.Should().Contain(e => e.ErrorCode == ValidationErrorCodes.NotNull);
166166
}
167167

168+
[Fact]
169+
public void CreditCard_should_fail_for_invalid_luhn_checksum()
170+
{
171+
var validator = new ContactInfoValidator();
172+
var contact = new ContactInfo { Email = "test@example.com", Website = "https://example.com", CreditCard = "4532015112830367" };
173+
174+
var result = validator.Validate(contact);
175+
176+
result.IsValid.Should().BeFalse();
177+
result.Errors.Should().Contain(e => e.PropertyName == "CreditCard" && e.ErrorCode == ValidationErrorCodes.CreditCard);
178+
}
179+
168180
//==============================================================================================
169181
/// <summary>
170182
/// Test model for Length validation.

tests/Fox.ValidationKit.Tests/ConditionalValidationTests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ public void CallWhenWithoutRule()
196196
{
197197
RuleFor(x => x.CompanyName).When(x => x.IsCompany);
198198
}
199+
200+
public void CallUnlessWithoutRule()
201+
{
202+
RuleFor(x => x.CompanyName).Unless(x => x.IsCompany);
203+
}
199204
}
200205

201206
//==============================================================================================
@@ -212,4 +217,19 @@ public void When_should_throw_when_called_without_rule()
212217

213218
act.Should().Throw<InvalidOperationException>().WithMessage("*must be called after*");
214219
}
220+
221+
//==============================================================================================
222+
/// <summary>
223+
/// Tests that Unless throws when called without a preceding rule.
224+
/// </summary>
225+
//==============================================================================================
226+
[Fact]
227+
public void Unless_should_throw_when_called_without_rule()
228+
{
229+
var validator = new EmptyValidator();
230+
231+
var act = () => validator.CallUnlessWithoutRule();
232+
233+
act.Should().Throw<InvalidOperationException>().WithMessage("*must be called after*");
234+
}
215235
}

tests/Fox.ValidationKit.Tests/InternalRulesDefensiveCodeTests.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,23 @@ public void CustomRule_should_throw_for_null_asyncPredicate()
9999
.Which.ParamName.Should().Be("asyncPredicate");
100100
}
101101

102+
//==============================================================================================
103+
/// <summary>
104+
/// Tests that CustomRule uses default error message when errorMessage is null.
105+
/// </summary>
106+
//==============================================================================================
107+
[Fact]
108+
public void CustomRule_should_use_default_error_message_when_null()
109+
{
110+
var rule = new CustomRule<TestModel, string?>("Value", (instance, value) => false, null!);
111+
var model = new TestModel { Value = "test" };
112+
113+
var errors = rule.Validate(model, "test").ToList();
114+
115+
errors.Should().ContainSingle();
116+
errors[0].Message.Should().Be("Value is invalid.");
117+
}
118+
102119
//==============================================================================================
103120
/// <summary>
104121
/// Tests that RuleForEachRule constructor throws for null propertyName.

tests/Fox.ValidationKit.Tests/PropertyValidatorTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,34 @@ public void AddRule_should_throw_for_null_rule()
6666
act.Should().Throw<ArgumentNullException>().WithParameterName("rule");
6767
}
6868
}
69+
70+
//==================================================================================================
71+
/// <summary>
72+
/// Tests for RuleBuilder defensive null checks.
73+
/// </summary>
74+
//==================================================================================================
75+
public sealed class RuleBuilderTests
76+
{
77+
//==============================================================================================
78+
/// <summary>
79+
/// Test model for RuleBuilder tests.
80+
/// </summary>
81+
//==============================================================================================
82+
private sealed class TestModel
83+
{
84+
public int Value { get; set; }
85+
}
86+
87+
//==============================================================================================
88+
/// <summary>
89+
/// Tests that RuleBuilder constructor throws for null propertyValidator.
90+
/// </summary>
91+
//==============================================================================================
92+
[Fact]
93+
public void Constructor_should_throw_for_null_propertyValidator()
94+
{
95+
var act = () => new RuleBuilder<TestModel, int>(null!);
96+
97+
act.Should().Throw<ArgumentNullException>().WithParameterName("propertyValidator");
98+
}
99+
}

tests/Fox.ValidationKit.Tests/ValidationResultDefensiveCodeTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,22 @@ public void Constructor_should_throw_for_null_errors()
3434
.WithInnerException<ArgumentNullException>()
3535
.Which.ParamName.Should().Be("errors");
3636
}
37+
38+
//==============================================================================================
39+
/// <summary>
40+
/// Tests that ValidationResult.AddError throws for null error.
41+
/// </summary>
42+
//==============================================================================================
43+
[Fact]
44+
public void AddError_should_throw_for_null_error()
45+
{
46+
var result = ValidationResult.Success();
47+
var addErrorMethod = typeof(ValidationResult).GetMethod("AddError", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
48+
49+
var act = () => addErrorMethod!.Invoke(result, [null!]);
50+
51+
act.Should().Throw<System.Reflection.TargetInvocationException>()
52+
.WithInnerException<ArgumentNullException>()
53+
.Which.ParamName.Should().Be("error");
54+
}
3755
}

0 commit comments

Comments
 (0)