I am trying to understand why my validation test is failing, when I expect it to pass.
Here is the code:
using FluentValidation;
namespace FluentValidationIssue
{
public class Model
{
public string Ean { get; set; }
internal List<string>? ProvidedEans { get; private set; }
internal string? SelectedSourceSetId { get; set; }
internal string? SetName { get; set; }
}
public class ModelValidator : AbstractValidator<Model>
{
public ModelValidator()
{
RuleFor(model => model.SetName).NotEmpty();
// nothing provided
RuleFor(model => model.SelectedSourceSetId)
.Empty()
.When(model => model.ProvidedEans is null || model.ProvidedEans!.Count == 0)
.WithMessage("Either an existing override/ymal set or a list of Eans must be provided.");
// both an existing and a list provided.
RuleFor(model => model.SelectedSourceSetId)
.NotEmpty()
.When(model => model?.ProvidedEans?.Count > 0)
.WithMessage("Choose either an existing override/ymal set or provide a list of Eans, not both.");
}
}
/// <summary> A program. </summary>
internal class Program
{
/// <summary> Main entry-point for this application. </summary>
static void Main(string[] args)
{
var model = new Model
{
Ean = "9780316587266",
WorkId = 1234,
SetName = "Set Name 1"
SelectedSourceSetId = "a59ea6d32f6444c8afef284e557ab319"
};
var validator = new ModelValidator();
var result = validator.Validate(model);
if (result.IsValid)
{
Console.WriteLine("The model is valid.");
}
else
{
Console.WriteLine("The model is invalid.");
foreach (var error in result.Errors)
{
Console.WriteLine($"- {error.PropertyName}: {error.ErrorMessage}");
}
}
}
}
}
Given that I populated the model.SelectedSourceSetId with a string value, I expect the first rule to pass. Except it is failing and returns my custom message.
If I leave model.SelectedSourceSetId set to null, the first rule passes, and it should fail.
If I provide values for both SelectedSourceSetId and ProvidedEans, the second rule passes, when it should fail.
I am trying to do a cross field check. The model needs to have either a SelectedSourceSetId or a list of strings (ProvidedEans), but not both.
The rules are:
If
SelectedSourceSetIdis an empty string/null and theProvidedEansis null orProvidedEansis an empty collection (Count == 0), than the error message should be triggered.If
SelectedSourceSetIdis an not empty/null and theProvidedEanscontains at least one item, than the error message should be triggered.
internalpropertiespublic? I've looked at your code a few times and that's the only notable difference.When(...)call to the last line in each rule? -RuleFor().NotEmpty().WithMessage().When()Eanbut not anyProvidedEans--- is that the bug?