Using NHamcrest with NUnit or XUnit

NHamcrest is supported out of the box with MbUnit, but there’s nothing stopping you using it with any other framework.

You just need to write the shim code, i.e. Assert.That.

For example, with NUnit it would look something like this:

public static void That<T>(T actual, IMatcher<T> matcher, string message, params object[] args)
{
	if (matcher.Matches(actual))
		return;
	
	var writer = new TextMessageWriter(message, args);

	WriteExpected(matcher, writer);

	WriteActual(actual, matcher, writer);

	throw new AssertionException(writer.ToString());
}

private static void WriteExpected(ISelfDescribing matcher, TextWriter writer)
{
	writer.Write(TextMessageWriter.Pfx_Expected);
	var description = new StringDescription();
	matcher.DescribeTo(description);
	writer.Write(description.ToString());
	writer.WriteLine();
}

private static void WriteActual<T>(T actual, IMatcher<T> matcher, TextWriter writer)
{
	writer.Write("  But ");
	var mismatchDescription = new StringDescription();
	matcher.DescribeMismatch(actual, mismatchDescription);
	writer.Write(mismatchDescription.ToString());
	writer.WriteLine();
}

For XUnit:

public static void That<T>(T actual, IMatcher<T> matcher)
{
	if (matcher.Matches(actual))
		return;

	var description = new StringDescription();
	matcher.DescribeTo(description);

	var mismatchDescription = new StringDescription();
	matcher.DescribeMismatch(actual, mismatchDescription);

	throw new MatchException(description.ToString(), mismatchDescription.ToString(), null);
}

public class MatchException : AssertActualExpectedException
{
	public MatchException(object expected, object actual, string userMessage) : base(expected, actual, userMessage)
	{
	}
}

And, for completeness, here’s the MbUnit version:

        public static void That<T>(T item, IMatcher<T> matcher, string messageFormat, params object[] messageArgs)
        {
            AssertionHelper.Verify(() =>
            {
                if (matcher.Matches(item))
                    return null;

                var description = new StringDescription();
                var mismatchDescription = new StringDescription();

                matcher.DescribeTo(description);
                matcher.DescribeMismatch(item, mismatchDescription);

                return new AssertionFailureBuilder("Expected " + description)
                    .SetMessage(messageFormat, messageArgs)
                    .AddLabeledValue("Expected", description.ToString())
                    .AddLabeledValue("But", mismatchDescription.ToString())
                    .ToAssertionFailure();
            });           
        }

4 thoughts on “Using NHamcrest with NUnit or XUnit

  1. Graham Hay's avatar Graham Hay May 10, 2012 / 2:45 pm

    To include the shims? I’d rather not couple it to any specific test frameworks.

    I could create an NHamcrest.[NUnit|XUnit] package, but it seems like overkill for one class.

  2. Søren Bjerregaard Vrist's avatar Søren Bjerregaard Vrist May 22, 2012 / 8:31 pm

    Yearh, you are probably right.

    Regarding the shims I’m having some troubles with the
    Assert.That(t, Is.InstanceOf()) if t : S and T : S as the type of Assert.That(T,IMatcher) wont allow the mismatches.

    I see that NUnit does this with something along the lines of Is.InstanceOf : object

Leave a comment