Skip to content

PropertyConstraint throws away the more helpful message in the base constraint result #2427

Closed
@jnm2

Description

@jnm2

Problem

PropertyConstraint keeps the base constraint description but throws away the actual comparison message and just prints the actual value.

Starting with a familiar example, Is.EquivalentTo:

var actual = new SomeClass { SomeProperty = { 2, 3, 5, 7 } };
Assert.That(actual.SomeProperty, Is.EquivalentTo(new List<int> { 2, 3, 5, 8 }));

Expected: equivalent to < 2, 3, 5, 8 >
But was: < 2, 3, 5, 7 >
Missing (1): < 8 >
Extra (1): < 7 >

But as soon as you compose it with PropertyConstraint:

var actual = new SomeClass { SomeProperty = { 2, 3, 5, 7 } };
Assert.That(actual, Has.Property("SomeProperty").EquivalentTo(new List<int> { 2, 3, 5, 8 }));

Expected: equivalent to < 2, 3, 5, 8 >
But was: < 2, 3, 5, 7 >

In that example, just printing the actual value is still pretty okay.
But when the value is a complex object that doesn't .ToString() to something you care about, you get something like this:

Expected: property SomeProperty [long description from custom constraint]
But was: <Appearance>

Assert.That(new SomeClass(), Has.Property("SomeComplexThing")
    .SomeCustomConstraint(expectedComplexThing));

Proposal

Here you can see the constraint, which understands the semantics of the actual value, getting thrown away. Only the actual value and success bool are retained:

var baseResult = BaseConstraint.ApplyTo(propValue);
return new ConstraintResult(this, baseResult.ActualValue, baseResult.IsSuccess);

Rather than the existing code below, I think we should have an internal-for-now ChainedConstraintResult class which delegates all its writing to the base constraint result:

internal class ChainedConstraintResult : ConstraintResult
{
    private readonly ConstraintResult _baseResult;

    public ChainedConstraintResult(IConstraint constraint, ConstraintResult baseResult) : base(constraint, baseResult.ActualValue, baseResult.Status)
    {
        _baseResult = baseResult;
    }

    public override void WriteActualValueTo(MessageWriter writer)
    {
        _baseResult.WriteActualValueTo(writer);
    }
}

PropertyConstraint would then do this:

var baseResult = BaseConstraint.ApplyTo(propValue);
return new ChainedConstraintResult(this, baseResult);

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions