Feature request: Provide a strongly typed variant of the Property constraint

Bug #901192 reported by Fabian Schmied
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
NUnit Framework
Triaged
Medium
Unassigned

Bug Description

[Issue now tracked at https://github.com/nunit/nunit-framework/issues/26]

Currently, NUnit supports a number of generic constraints that define the type of the tested expression at compile time (if they succeed): Is.TypeOf<T>(), Is.AssignableTo<T>(), and Is.InstanceOf<T>(). (Note that Is.AssignableFrom<T>() is not a candidate for this feature request because it only defines a derived type!)

Those constraint factory methods currently return instances of non-generic expression types (e.g., ExactTypeConstraint, etc.) that inherit the ordinary, untyped constraint expression factory methods, so that you can write, for example: Is.TypeOf<object>().With.Property ("P").EqualTo (42). Note that when "With" is called, the type information specified at the TypeOf<T> call gets lost and the Property constraint needs to take the property name by string rather than, for example, by expression.

Passing the property name as string is bad as an invalid name will not trigger a compile-time error and as automated refactorings (e.g., renaming the property) will not take notice of the property name.

Therefore, change TypeOf<T>, AssignableTo<T>, and InstanceOf<T> to return generic subclasses of the contraint types (e.g., ExactTypeConstraint<T>) that redefine Constraint.With to retain the type information. Provide generic variants of ConstraintExpression and ResolvableConstraintExpression to allow for nested strongly typed constraints. Then provide a generic version of the Property constraint factory method.

Here is what the code could look like for NUnit 2.6 (with non-breaking changes).

public class ExactTypeConstraint<T> : ExactTypeConstraint
{
  public new ConstraintExpression<T> With { get { ... } }
}

public class ConstraintExpression<T> : ConstraintExpression
{
  public new ConstraintExpression<T> With { get { ... } }
  public new ConstraintExpression<T> And { get { ... } }
  // ...

  public ResolvableConstraintExpression<T> Property<TR> (Expression<Func<T, TR>> propertyAccessor);
}

public class ResolvableConstraintExpression<T> : ResolvableConstraintExpression
{
  public new ConstraintExpression<T> With { get { ... } }
  public new ConstraintExpression<T> And { get { ... } }
}

That way, one could write constraints similar to:
Is.TypeOf<object>().With.Property (o => o.P).EqualTo (42).And.Property (o => o.P2).EqualTo (43)

Changed in nunitv2:
status: New → Triaged
importance: Undecided → Medium
milestone: none → 2.6.0
tags: added: feature
Revision history for this message
Charlie Poole (charlie.poole) wrote :

This is a good idea but requires .NET 3.5 to use Expression and also has some ramifications on how ContraintExpressions work in general. Pushing it to NUnit 3.0, where we will have separate builds for .NET 2.0, 3.5 and 4.0.

affects: nunitv2 → nunit-3.0
Changed in nunit-3.0:
milestone: 2.6.0 → none
tags: added: framework
description: updated
tags: added: github
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.