Skip to content

Migrate from xUnit Assert to Axiom

If your tests are mostly built on Assert.*, Axiom is designed to give you a direct migration path without forcing a broad rewrite of how the suite is structured.

That does not mean every xUnit suite should migrate. If the current tests are clear and the team is not feeling friction, leaving them alone may be the better engineering choice.

What The Straight Rewrite Looks Like

Many common xUnit assertions map directly to Should() assertions:

var actualCount = 3;
string? name = "Alice";
var isReady = true;
var items = new[] { "admin", "user" };

actualCount.Should().Be(3);
name.Should().NotBeNull();
isReady.Should().BeTrue();
items.Should().Contain("admin");

That directness is the main reason teams can migrate in stages instead of pausing all test work for a large assertion rewrite.

Where The Built-In Analyzers Help

The Axiom analyzers cover a growing set of safe, mechanical xUnit rewrites. They are useful when you want to move a codebase gradually and reserve manual review time for the tests that really need judgment.

That now includes awaited async exception assertions such as Assert.ThrowsAsync<T>(...), Assert.ThrowsAsync<T>(paramName, ...), and Assert.ThrowsAnyAsync<T>(...) when they map directly onto Axiom's async throw assertions without changing value flow. If the old test used the returned exception, the code fix keeps that explicit by appending .Thrown.

Install path:

dotnet add package Axiom.Assertions

That default package already brings the analyzers with it.

Where You Still Need Judgment

Some tests should stay manual during migration:

  • assertions with precision rules or xUnit comparer overloads that do not have a direct, semantics-preserving Axiom equivalent yet
  • structural comparisons that are really object-graph assertions
  • exception assertions where the returned exception is used in detail
  • non-awaited async exception assertions that would need a broader rewrite than a direct awaited Should() conversion
  • tests that currently hide several behaviors inside a long chain of Assert.* calls

For those cases, use the broader Migrating to Axiom guide.

When Axiom Can Be A Reasonable Migration Target

Axiom can be a reasonable xUnit Assert migration target when you want:

  • direct scalar rewrites for common assertions
  • deterministic failure output
  • explicit grouped failures with Batch
  • analyzer support that helps with the obvious rewrites first

The case is strongest when those benefits line up with the assertion shapes your suite already uses today.

When A Different Move May Be Better

If your team is not trying to leave framework assertions yet, or if you mainly want the most familiar assertion ecosystem possible, it may be reasonable to stay with xUnit Assert for now or assess another fluent library first.

If you are making that choice, these pages can help: