| Property | Value |
|---|---|
| Category | Constraints (JustDummies.Constraints) |
| Severity | 🔵 Info |
| Enabled by default | Yes |
A value written into a value set is refused by a constraint declared on the same chain, so no draw can ever yield it. The rule reads the string families and the numeric ones — every integer type and decimal.
A value set composes with the other constraints: each supplied value passes them or fails them, and the domain is the values that pass. A value that fails leaves the domain in silence — only an emptied domain is reported, and that at declaration. Between “every value survives” and “none does” there is no signal, so a pool can read as five values and draw from three.
This is the dual of JD024. That rule reports a constraint that narrows nothing; this one reports a value that nothing lets through.
Noncompliant
string code = Any.String().OneOf("abc", "de").WithLength(3).Generate();
"de" is two characters, so WithLength(3) refuses it and the pool is one value, not two.
Compliant
string code = Any.String().OneOf("abc", "xyz").WithLength(3).Generate();
Either repair closes it, and which one is right is not something the rule can know: drop the value from the pool, or loosen the constraint that refuses it.
Info rather than Warning
Narrowing a shared pool at one call site is exactly what declaring a constraint beside a value set is for. A team may keep one catalogue and draw a different slice of it in each test; a rule that called that a defect would be wrong more often than right. So this states a fact to weigh, never a verdict.
That holds only while the chain still draws something. A pool nothing survives is not a narrowing — it throws at declaration — so this rule goes quiet there and JD015 reports it once, about the chain, at the severity a chain that throws deserves. Listing every value here as well would say the same thing a second time, in a register that reads as “this still works”.
What it does not flag
- A pool held in a variable, which is the case that matters most and the one a build-time answer cannot reach. A catalogue loaded from a file or shared through a field is answered at run time instead, by
IPoolInspection<T>— against the values actually supplied, and with every constraint that refuses each one. - A binary floating-point pool —
Any.Double(),Any.Single(),Any.Half()— and the 128-bit integers. Adoubleconstant has no exactdecimal, and decimal cannot hold the 128-bit range, so judging either through it could refuse a value the run time admits. Out of scope rather than approximated. - A constraint whose argument is not a compile-time constant. It is skipped rather than guessed at, so a value it alone refuses goes unreported. Under-reporting is the safe direction here: a value this rule does report is genuinely refused, because adding constraints only ever removes more values.
- A chain split across statements or variables, and a chain with no value set at all.
- A pool no value survives — JD015’s, per the paragraph above.
- A conflict-asserting negative test, where the chain is the whole body of a lambda argument.