MSTest v2: Create new asserts

 
 
  • Gérald Barré

This post is part of the series 'MSTest v2'. Be sure to check out the rest of the blog posts of the series!

MSTest v2 is extensible. In a previous post, we saw how to extend data tests. In this post, we'll see how to create new asserts.

The MSTest framework contains lots of assert methods. They are all located in 3 classes: Assert, StringAssert, CollectionAssert. Sometimes, you want more assertions. In this case, you can create your assert methods.

An assert method is a method that validates a value satisfies specific criteria. If the criteria are not satisfied, an exception is thrown. In MSTest, the exception is of type AssertFailedException, but you can throw any kind of exception.

Let 's create a custom assert to ensure a string is equal to another one. If the 2 strings are different the message contains a formatted diff that shows blank characters and the first different character:

C#
internal static class MyAssert
{
    public static void StringEquals(string expected, string actual)
    {
        if (expected == actual)
            return;

        throw new AssertFailedException(GetMessage(expected, actual));
    }

    private static string GetMessage(string expected, string actual)
    {
        var expectedFormat = ReplaceInvisibleCharacters(expected);
        var actualFormat = ReplaceInvisibleCharacters(actual);

        // Get the index of the first different character
        var index = expectedFormat.Zip(actualFormat, (c1, c2) => c1 == c2).TakeWhile(b => b).Count();
        var caret = new string(' ', index) + "^";

        return $@"Strings are different.
Expect: <{expectedFormat}>
Actual: <{actualFormat}>
         {caret}";
    }

    private static string ReplaceInvisibleCharacters(string value)
    {
        return value
            .Replace(' ', '·')
            .Replace('\t', '→')
            .Replace("\r", "\\r")
            .Replace("\n", "\\n");
    }
}

In case the values are different, the output of the test run look like:

C#
[TestMethod]
public void Test1()
{
    MyAssert.StringEquals("abc def", "abc  def");
}
Message: Strings are different.
Expect: <abc·def>
Actual: <abc··def>
             ^

Ok, that great. But MSTest v2 provides a way to integrate your assert into the provided asserts. If you look at the IntelliSense, you may have noticed the That property. The property has no member:

So, why the hell is this property? The idea is to provide a property that returns an instance of Assert. This allows you to create extension methods 😃 (of course, the same property exists in StringAssert and CollectionAssert)

So, you can rewrite the assert method as an extension method:

C#
internal static class MyAssert
{
    public static void StringEquals(this Assert assert, string expected, string actual)
    {
        if (expected == actual)
            return;

        throw new AssertFailedException(GetMessage(expected, actual));
    }

    // ...
}

Now, you can use the extension method in the test:

C#
[TestMethod]
public void Test1()
{
    Assert.That.StringEquals("abc def", "abc  def");
}

This syntax is more readable as the line is a valid English sentence.

#Conclusion

Writing custom assert methods allows us to create more useful messages, or to create business-specific asserts. MSTest v2 provides a nice way to create custom assert by using an extension method. The That property is very smart 😃

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?Buy Me A Coffee💖 Sponsor on GitHub