I like the IArgMatcher and abstract base class idea! Much cleaner.
Something like:
public interface IArgMatcher
{
void Match(object arg);
bool IsMatch();
}
public abstract class ArgMatcher<T> : IArgMatcher
{
private ICollection<MatchFailure> _matchFailures = new
List<MatchFailure>();
protected abstract void Match(T arg);
protected void NonMatch(Expression<Func<T, object>>
memberExpression, object expected) { ... }
protected void NonMatch(Expression<Func<T, object>>
memberExpression, object expected, string message) { ... }
public void Match(object arg)
{
Match(arg as T);
}
public bool IsMatch()
{
if(_matchFailures.Any())
{
throw new ArgumentMismatchException(_matchFailures);
}
}
}
The NonMatch methods would take a member expression (which would aide
in refactoring, and also allow us access to the actual value of the
member) and take care of creating the MatchFailure objects and adding
them to the _matchFailures collection.
On Jul 15, 1:20 am, David Tchepak <
tche...@gmail.com> wrote:
> Completely agree NSubstitute needs to give more help with this.
>
> Maybe pass in a builder of some sort rather than forcing people to new-up an
> IEnumerable<CriteriaFailure>s?
>
> sub.Received().SomeCall(Arg.Is<Foo>((arg, result) => {
> if (arg.Something != 2) result.NonMatch("Something not 2");
> if (arg.SomethingElse == null) result.NonMatch("SomethingElse is null");
> //...
> }));
>
> This might be too messy to do inline, so maybe we'd want to extract custom
> matchers to a method. In which case would it be cleaner to put it behind an
> IArgMatcher interface, maybe with an abstract base class to help quickly
> implement matchers?
>
> On Fri, Jul 15, 2011 at 11:06 AM, Will Green <
wdg.hotgazpa...@gmail.com>wrote:
>
>
>
>
>
>
>
> > I've been struggling with the issue of matching complex objects
> > (objects with multiple properties). Using a Predicate<T> with
> > Arg.Is<T> is nice for simple objects, but when your object has, say,
> > 10 properties that you want to verify, and one of them causes the
> > criteria defined in the Predicate to fail, you don't get any
> > indication *which* property failed the criteria. It also seems quite
> > tedious to have a single assert for each property of the object.
>
> > What I'm thinking is a sort of advanced API for matching objects. The
> > first thing that comes to mind is adding an overload to Arg.Is that
> > takes a Func<T,IEnumerable<CriteriaFailure>>. In this Func, you would
> > check each property as appropriate, and add CriteriaFailure objects to
> > a list that the Func returns. If the list is not empty, NSubstitute
> > would throw an assertion exception that would list out each error, so
> > you'd know what property failed.
>
> > The CriteriaFailure object could have the Member name, the Expected
> > value, the Actual Value, and an optional message.
>
> > What do you think?
>
> > ==
> > Will Green
> >
w...@hotgazpacho.org