And this is why I like NUnit's "new" constraint model

 
event

Yes, I do.

Since I first saw that fluent and verbose semi-fluent API (Assert.That(actual, Is.Blah(...)))I knew we were to become more than good friends. I saw potential in that relationship.

I know people that just don't like fluent interfaces because they are so in love with their superior dynamic languages and because fluent interfaces came from Java, and we all know that nothing good can come from the enemies, right? (NHibernate, NUnit, Log4Net,... evil or useless code, or worse yet! evil and useless code) </sarcasm>

Jokes aside, it is not just that I believe assertions using this model read slightly better or that arguments are better ordered (in my opinion), but it also allows for better extensibility with less work.

Today's case is (again) against code duplication and as a very nice side effect making our unit tests cleaner and slightly more readable. Not so bad in one go...

Also, as with many of my posts, the code I am going to use is "real" production code. Which I also think is itself a good thing and thus I keep doing it.

Let's put things in perspective: we have a class PresentableType that needs to be presented on a screen. This presentable object has a couple of complex properties (of type ComplexType). It makes a lot of sense that this class can be null or that its properties can be null when we are using the object in our domain, but it does make no sense to have null when we display it on the screen. With these premises what I did was create an extension method that can transform null instances of both the PresentableType and ComplexType into some sort of NullObject (as in NullObject pattern). This null object is a singleton instance of ComplexType (almost same technique used in the framework in multiple places, int.MinValue for instance), so that only one instance of the null object can live and reference checking can be used.

One might argue that an extension method is not the best solution as one may feel weird to invoke a method in a null instance and get a not null result. Particularly I feel this issue bothers me not, and since extension method are a compact and convenient way to add behavior when and where is needed to an already existing object, I am for using it in this case.

Let's have a look at both classes:

[Serializable]
public class ComplexType
{
[Obsolete("Serialization Only")]
public ComplexType() { }
public ComplexType(int id, string title)
{
Id = id;
Title = title;
}
public int Id { get; private set; }
public string Title { get; private set; }
}
[Serializable]
public class PresentationType
{
[Obsolete("Serialization Only")]
public PresentationType() { }
public PresentationType(ComplexType foo, ComplexType bar)
{
Foo = foo;
Bar = bar;
}
public ComplexType Foo { get; private set; }
public ComplexType Bar { get; private set; }
}
view raw types.cs hosted with ❤ by GitHub

And the extension methods:

public static class TypeExtensions
{
public static ComplexType NotAvailableIfNull(this ComplexType instance)
{
ComplexType result = instance;
if (instance == null)
{
result = NotAvailableComplexType.Instance;
}
return result;
}
public static PresentationType NotAvailableIfNull(this PresentationType instance)
{
PresentationType result;
if (instance != null)
{
result = new PresentationType(instance.Foo.NotAvailableIfNull(), instance.Bar.NotAvailableIfNull());
}
else
{
result = new PresentationType(NotAvailableComplexType.Instance, NotAvailableComplexType.Instance);
}
return result;
}
public static IEnumerable<PresentationType> NotAvailableIfNull(this IEnumerable<PresentationType> instances)
{
List<PresentationType> result = null;
if (instances != null)
{
result = new List<PresentationType>();
foreach (var image in instances)
{
result.Add(image.NotAvailableIfNull());
}
}
return result;
}
}
public sealed class NotAvailableComplexType
{
public static ComplexType Instance { get { return Nested.instance; } }
class Nested
{
// Explicit static constructor to tell C# compiler not to mark type as beforefieldinit
static Nested() { }
internal static readonly ComplexType instance = new ComplexType(-1, null);
}
}

The problem I was trying to solve was a simple one: how to unit test the extension methods.

One simple way of doing it is using standard assertions over each an every of the properties of PresentableType. It works, no doubt about it, but it's ugly and generates a lot of duplication for all the possible cases: instance on PresentableType is null, the instance is not null but both complex properties are, only one of the properties is null, etc...  Code is worth a thousand words:

[TestFixture]
public class Tester
{
[Test]
public void NotAvailableIfNull_NotNullProperties_OriginalProperties()
{
PresentationType instance = new PresentationType(MockRepository.GenerateStub<ComplexType>(), MockRepository.GenerateStub<ComplexType>());
PresentationType subject = instance.NotAvailableIfNull();
Assert.That(subject, Is.Not.SameAs(instance));
Assert.That(subject.Foo, Is.SameAs(instance.Foo));
Assert.That(subject.Bar, Is.SameAs(instance.Bar));
}
[Test]
public void NotAvailableIfNull_NullFoo_PartialNotAvailable()
{
PresentationType instance = new PresentationType(null, MockRepository.GenerateStub<ComplexType>());
PresentationType subject = instance.NotAvailableIfNull();
Assert.That(subject, Is.Not.Null);
Assert.That(subject.Foo, Is.SameAs(NotAvailableComplexType.Instance));
Assert.That(subject.Bar, Is.SameAs(instance.Bar));
}
[Test]
public void NotAvailableIfNull_NullBar_PartialNotAvailable()
{
PresentationType instance= new PresentationType(MockRepository.GenerateStub<ComplexType>(), null);
PresentationType subject = instance.NotAvailableIfNull();
Assert.That(subject, Is.Not.Null);
Assert.That(subject.Foo, Is.SameAs(image.Foo));
Assert.That(subject.Bar, Is.SameAs(NotAvailableComplexType.Instance));
}
[Test]
public void NotAvailableIfNull_Null_CompleteNotAvailable()
{
PresentationType instance = null;
PresentationType subject = instance.NotAvailableIfNull();
Assert.That(subject, Is.Not.Null);
Assert.That(subject.Foo, Is.SameAs(NotAvailableComplexType.Instance));
Assert.That(subject.Bar, Is.SameAs(NotAvailableComplexType.Instance));
}
}
view raw tester.cs hosted with ❤ by GitHub

Why not hide all that duplication under a NUnit Constraint type that is applied to the PresentableType instance (or null, for what is worth)? Actually we would need a couple of cases to handle, as the case in which the instance is null is slightly different, requiring different assertions. No problem, as a different class is created for that purpose. Let's have a look at how these constraints look like:

public class PartialConstraint : Constraint
{
private readonly PresentationType _expected;
public PartialConstraint(PresentationType expected)
{
_expected = expected;
}
#region Overrides of Constraint
public override bool Matches(object actualItem)
{
return matches(actualItem as PresentationType);
}
private string _message;
public override void WriteDescriptionTo(MessageWriter writer)
{
writer.Write(_message);
}
#endregion
public bool matches(PresentationType typedActual)
{
bool result = false;
if (typedActual != null)
{
Assert.That(typedActual, Is.Not.SameAs(_expected));
Assert.That(typedActual.Foo,
Is.SameAs(_expected.Foo ?? NotAvailableComplexType.Instance));
Assert.That(typedActual.Bar,
Is.SameAs(_expected.Bar ?? NotAvailableComplexType.Instance));
result = true;
}
else
{
_message = "Instance is not a MultiImage";
}
return result;
}
}
public class TotalConstraint : Constraint
{
#region Overrides of Constraint
public override bool Matches(object actualItem)
{
bool result = false;
PresentationType typedActual = actualItem as PresentationType;
if (typedActual != null)
{
Assert.That(typedActual, Is.Not.Null);
Assert.That(typedActual.Foo, Is.SameAs(NotAvailableComplexType.Instance));
Assert.That(typedActual.Bar, Is.SameAs(NotAvailableComplexType.Instance));
result = true;
}
else
{
_message = "Instance is not a MultiImage";
}
return result;
}
private string _message;
public override void WriteDescriptionTo(MessageWriter writer)
{
writer.Write(_message);
}
#endregion
}
view raw constraints.cs hosted with ❤ by GitHub

And let's see how a unit test might look with this extended Constraint:

[TestFixture]
public class Tester
{
[Test]
public void NotAvailableIfNull_NotNullProperties_OriginalProperties()
{
PresentationType instance = new PresentationType(MockRepository.GenerateStub<ComplexType>(), MockRepository.GenerateStub<ComplexType>());
PresentationType subject = instance.NotAvailableIfNull();
Assert.That(subject, new PartialConstraint(instance));
}
[Test]
public void NotAvailableIfNull_NullFoo_PartialNotAvailable()
{
PresentationType instance = new PresentationType(null, MockRepository.GenerateStub<ComplexType>());
PresentationType subject = instance.NotAvailableIfNull();
Assert.That(subject, new PartialConstraint(instance));
}
[Test]
public void NotAvailableIfNull_NullBar_PartialNotAvailable()
{
PresentationType instance = new PresentationType(MockRepository.GenerateStub<ComplexType>(), null);
PresentationType subject = instance.NotAvailableIfNull();
Assert.That(subject, new PartialConstraint(instance));
}
[Test]
public void NotAvailableIfNull_Null_CompleteNotAvailable()
{
PresentationType image = null;
PresentationType subject = image.NotAvailableIfNull();
Assert.That(subject, new TotalConstraint());
}
}

Concise. Right? But if at the beginning of this long post I mentioned that I liked how the assertion can be read, I just stepped back on that front. But with a little effort we can make it look nicer. Making things look nicer in unit tests is not always (mostly never) a requirement, but if it helps readability I consider it's for the good. What if we could use a static builder, the very same way NUnit uses the SyntaxHelpers.Is class? A bit of a trick with static properties and extension methods...

public static class Must
{
public class EntryPointBe
{
internal EntryPointBe() { }
}
private static readonly EntryPointBe _entryPointBe = new EntryPointBe();
public static EntryPointBe Be { get { return _entryPointBe; } }
}
public static class MustExtensions
{
public static Constraint PartiallyConstrained(this Must.EntryPointBe entryPoint, PresentationType expected)
{
return new PartialConstraint(expected);
}
public class EntryPointBy
{
internal EntryPointBy() { }
}
public static EntryPointBy PartiallyConstrained(this Must.EntryPointBe entryPoint)
{
return new EntryPointBy();
}
public static Constraint By(this EntryPointBy entryPoint, PresentationType expected)
{
return new PartialConstraint(expected);
}
public static Constraint TotallyContrained(this Must.EntryPointBe extended)
{
return new TotalConstraint();
}
}
view raw must.cs hosted with ❤ by GitHub

...leaves the syntax of the tests concise, pretty readable and free of duplication. For those who say that is has to be pretty self-explaining what the unit test does, the real "meat" of the assertion is just one click away. Note that the lines "Assert.That(subject, Must.Be.PartiallyConstrained(instance));" and "Assert.That(subject, Must.Be.PartiallyConstrained().By(instance));" are completely equivalent. They are just a bit of an experiment that I was doing while migrating the code to be "bloggable":

[TestFixture]
public class Tester
{
[Test]
public void NotAvailableIfNull_NotNullProperties_OriginalProperties()
{
PresentationType instance = new PresentationType(MockRepository.GenerateStub<ComplexType>(), MockRepository.GenerateStub<ComplexType>());
PresentationType subject = instance.NotAvailableIfNull();
Assert.That(subject, Must.Be.PartiallyConstrained(instance));
Assert.That(subject, Must.Be.PartiallyConstrained().By(instance));
}
[Test]
public void NotAvailableIfNull_NullFoo_PartialNotAvailable()
{
PresentationType instance = new PresentationType(null, MockRepository.GenerateStub<ComplexType>());
PresentationType subject = instance.NotAvailableIfNull();
Assert.That(subject, Must.Be.PartiallyConstrained(instance));
Assert.That(subject, Must.Be.PartiallyConstrained().By(instance));
}
[Test]
public void NotAvailableIfNull_NullBar_PartialNotAvailable()
{
PresentationType instance = new PresentationType(MockRepository.GenerateStub<ComplexType>(), null);
PresentationType subject = instance.NotAvailableIfNull();
Assert.That(subject, Must.Be.PartiallyConstrained(instance));
Assert.That(subject, Must.Be.PartiallyConstrained().By(instance));
}
[Test]
public void NotAvailableIfNull_Null_CompleteNotAvailable()
{
PresentationType image = null;
PresentationType subject = image.NotAvailableIfNull();
Assert.That(subject, Must.Be.TotallyContrained());
}
}
view raw tester-must.cs hosted with ❤ by GitHub

Not that bad for testing code, uh?