Fortunately, there's a really easy way to (unit) test html helpers for valid markup. For this, we'll use HtmlAgilityPack, "an HTML parser written in C#".

In the following example, I assume that you don't rely on the HtmlHelper instance in your helper method. The assertion itself is done using Fluent Assertions, a really nice library for writing more readable test cases/assertions.

var replacedHtmlString = ((HtmlHelper) null).ReplaceToggleToken(SampleText, trackingKey);

var htmlDocument = new HtmlDocument();

Even though this code is straight forward and rather short, there will be a lot of repetition when testing multiple html helpers or testing multiple cases of the same helper. To overcome this, we can introduce a custom Fluent Assertions extension.

Such an extension consists of the assertions class:

public class HtmlStringAssertions : ReferenceTypeAssertions<HtmlString, HtmlStringAssertions> {

    public HtmlStringAssertions(HtmlString instance) {
        Subject = instance;

    protected override string Identifier => "HtmlString";

    public AndConstraint<HtmlStringAssertions> BeValidHtml(string because = "", params object[] becauseArgs) {
            .BecauseOf(because, becauseArgs)
            .Given(() => {
                var htmlDocument = new HtmlDocument();

                return htmlDocument;
            .ForCondition(htmlDocument => !htmlDocument.ParseErrors.Any())
            .FailWith("Expected {context:HtmlString} to contain valid HTML{reason}.");

        return new AndConstraint<HtmlStringAssertions>(this);


And the extension class:

public static class HtmlStringExtensions  {

    public static HtmlStringAssertions Should(this HtmlString instance) {
        return new HtmlStringAssertions(instance); 


Now, all that's left to do is to adjust the test case:

var replacedHtmlString = ((HtmlHelper)null).ReplaceToggleToken(SampleText, trackingKey);


And now, happy testing :)