fix(validation): return no problems for null reference instance in Rule.Validate
Rule<T,TProperty>.Validate cast a null instance to T and validated it, so a reference T whose accessor dereferences the instance threw NullReferenceException on a direct validator.Validate(context) with a null instance. Guard the null-instance path and return no problems instead.
This commit is contained in:
parent
68194d3cb3
commit
552f88df18
3 changed files with 13 additions and 1 deletions
|
|
@ -52,6 +52,7 @@ To have a consistent experience across all packages, some public interfaces have
|
||||||
- **request.result:** Correct the namespace in the `Prelude` doc comment (`Geekeey.Extensions.Result` → `Geekeey.Request.Result`)
|
- **request.result:** Correct the namespace in the `Prelude` doc comment (`Geekeey.Extensions.Result` → `Geekeey.Request.Result`)
|
||||||
- **request.result:** Fold `IsSuccess` into `Result<T>.GetHashCode` to avoid collisions between a failure and a success value whose hash is `0`
|
- **request.result:** Fold `IsSuccess` into `Result<T>.GetHashCode` to avoid collisions between a failure and a success value whose hash is `0`
|
||||||
- **request.validation:** Guard null comparison bounds in `GreaterThan`/`LessThan`/`Between` etc. so a `null` bound no longer throws (`NullReferenceException`)
|
- **request.validation:** Guard null comparison bounds in `GreaterThan`/`LessThan`/`Between` etc. so a `null` bound no longer throws (`NullReferenceException`)
|
||||||
|
- **request.validation:** Return no problems when validating a `null` instance of a reference type instead of dereferencing it (`NullReferenceException`)
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,17 @@ internal sealed class ValidatorTests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task I_can_validate_with_a_null_instance_without_throwing()
|
||||||
|
{
|
||||||
|
var validator = new PropertyValidator<Person?, string?>(person
|
||||||
|
=> person!.Name, rule => rule.Must(value => value is not null, "Name is required."));
|
||||||
|
|
||||||
|
var result = validator.Validate((Person?)null);
|
||||||
|
|
||||||
|
await Assert.That(result.IsValid).IsTrue();
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task I_can_compose_nested_validators_and_aggregate_property_paths()
|
public async Task I_can_compose_nested_validators_and_aggregate_property_paths()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ internal abstract record Rule<T, TProperty> : Rule
|
||||||
|
|
||||||
if (context.Instance is null && default(T) is null)
|
if (context.Instance is null && default(T) is null)
|
||||||
{
|
{
|
||||||
return Validate((T)context.Instance!, context);
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
var actualType = context.Instance?.GetType().FullName ?? "null";
|
var actualType = context.Instance?.GetType().FullName ?? "null";
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue