DEV Community

Cover image for How to create custom assertions in C# with MSTest
Cesar Aguirre
Cesar Aguirre

Posted on • Updated on • Originally published at canro91.github.io

How to create custom assertions in C# with MSTest

I originally posted an extended version of this post on my blog a couple of weeks ago. It's part of a series I've been publishing, called Unit Testing 101.

Last time, we went through some best practices to write better assertions on our tests. This time, let's focus on how to use custom assertions in our tests.

Use custom assertions to encapsulate multiple assertions on a single method and to express assertions in the same language as the domain model. Write custom assertions with local methods or extension methods on the result object of the tested method or on the fakes objects.

We can either create custom assertions on top of MSTest Assert class. And, our own Verify() methods on Moq mocks.

Custom MSTest Assert methods

Let's write a custom assertion method with MSTest.

To write custom assertions with MSTest, write an extension method on top of the Assert class. Then, compare the expected and actual parameters and throw an AssertFailedException if the comparison fails.

Here, we're creating a StringIsEmpty() method.

internal static class CustomAssert
{
    public static void StringIsEmpty(this Assert assert, string actual)
    {
        if (string.IsNullOrEmpty(actual))
            return;

        throw new AssertFailedException($"Expect empty string but was {actual}");
    }
}
Enter fullscreen mode Exit fullscreen mode

Then, we can use StringIsEmpty() with the That property. Like this,

Assert.That.StringIsEmpty("");
Enter fullscreen mode Exit fullscreen mode

With this new assertion method, we can refactor one of our tests for Stringie, a (fictional) library to manipulate strings. We used Stringie to learn 4 common mistakes when writing tests and 4 test naming conventions.

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Stringie.UnitTests;

[TestClass]
public class RemoveTests
{
    [TestMethod]
    public void Remove_NoParameters_ReturnsEmpty()
    {
        string str = "Hello, world!";

        string transformed = str.Remove();

        Assert.That.StringIsEmpty(transformed); // 👈
    }
}
Enter fullscreen mode Exit fullscreen mode

With our custom StringIsEmpty() method, our test is more readable. And, we wrote the tests in the same terms as our domain language.

Even better, since our StringIsEmpty() method deals with strings, we can use the StringAssert class as parameter in our custom method and rename it to IsEmpty().

Voilà! That's how to write custom assertions with MSTest. With custom assertions we have our tests written in the same terms as our domain model.

Remember, you can simply write private methods grouping your regular assertions and share them in a base test class. Or write extensions methods on the output of the method being tested. That would make your test even easier to read.

Upgrade your unit testing skills with my course: Mastering C# Unit Testing with Real-world Examples on my Gumroad page. Practice with hands-on exercises and learn best practices by refactoring real-world unit tests.

Happy testing!

Top comments (2)

Collapse
 
justsomeone profile image
AlexMauch

Very good post. I remain with one question: how can I "force" the Visual Studio TestExplorer to recognize methods, that are being tested inside a custom assertion method? I want to see a green tick and the number of test on each method that I have tested...

Collapse
 
canro91 profile image
Cesar Aguirre

Well, I've used custom assertion methods inside the regular test methods (annotated with [TestMethod] for MSTest) and I've never needed extra changes to make the test appear on the Test Explorer.
With our custom assertions, we only replace the last A (Assert) of the AAA principle, not the whole test method.