A .NET tool that automatically rewrites FluentAssertions assertions into their xUnit equivalents. Point it at a solution and it migrates .Should() assertions to Assert.* calls using Roslyn.
Install
No framework information available.
README
FluentAssertions to xUnit Migration Tool
A .NET tool that automatically converts FluentAssertions test assertions to their xUnit equivalents. Regardless of how we feel about the upcoming license changes in the next major version of FluentAssertions, I imagine many of us will find ourselves in the position of having to strip out FluentAssertions of our codebases. I know I will. This tool tries to automate that process as much as possible.
Based on the following sources
- https://github.com/xunit/xunit/issues/3133
- https://www.meziantou.net/using-roslyn-to-analyze-and-rewrite-code-in-a-solution.htm
- https://stackoverflow.com/questions/31481251/applying-multiple-changes-to-a-solution-in-rosly
- ...
Installation
dotnet tool install -g FluentAssertionsMigrator
Building the Tool yourself
cd C:\...\fluentassertions-migrator\src\
dotnet pack
dotnet tool install -g FluentAssertionsMigrator
Usage
Make a backup of your solution (or use version control like a sane person) before you run this tool
Before you run this tool, be sure to restore the nuget packages of your solution. This tool uses semantic analysis in some places that will not work without these packages.
migrate-fluentassertions <path-to-solution-file>
Example:
migrate-fluentassertions C:\Projects\MySolution.sln
What it does
This tool analyzes your test files and converts FluentAssertions API calls to their xUnit equivalents. It handles many common assertion patterns including:
Equality
.Should().Be()βAssert.Equal().Should().NotBe()βAssert.NotEqual().Should().BeSameAs()βAssert.Same().Should().NotBeSameAs()βAssert.NotSame().Should().BeEquivalentTo()βAssert.Equivalent()
Boolean checks
.Should().BeTrue()βAssert.True().Should().BeFalse()βAssert.False()
Null checks
.Should().BeNull()βAssert.Null().Should().NotBeNull()βAssert.NotNull()
Collections
.Should().BeEmpty()βAssert.Empty().Should().NotBeEmpty()βAssert.NotEmpty().Should().HaveCount()βAssert.Equal(count)orAssert.Single()orAssert.Empty().Should().Contain()βAssert.Contains().Should().NotContain()βAssert.DoesNotContain().Should().ContainSingle()βAssert.Single().Should().BeNullOrEmpty()βAssert.False(?.Any() ?? false).Should().NotBeNullOrEmpty()βAssert.True(?.Any()).Should().BeOneOf()βAssert.Contains().Should().ContainEquivalentOf()βAssert.Contains().Should().NotContainEquivalentOf()βAssert.DoesNotContain().Should().Equal()βAssert.Equal().Should().OnlyContain()βAssert.All(collection, x => Assert.True(predicate)).Should().NotEqual()βAssert.NotEqual().Should().HaveCountGreaterThan()βAssert.True(x.Count() > n).Should().HaveCountGreaterThanOrEqualTo()βAssert.True(x.Count() >= n)
Dictionaries
.Should().ContainKey()βAssert.Contains(key, dictionary).Should().NotContainKey()βAssert.DoesNotContain(key, dictionary)
Strings
.Should().StartWith()βAssert.StartsWith().Should().EndWith()βAssert.EndsWith().Should().ContainAll()βAssert.All(strings, s => Assert.Contains(s, x)).Should().MatchRegex()βAssert.Matches().Should().NotMatchRegex()βAssert.DoesNotMatch().Should().HaveLength()βAssert.Equal(n, x.Length).Should().BeNullOrWhiteSpace()βAssert.True(string.IsNullOrWhiteSpace(x)).Should().NotBeNullOrWhiteSpace()βAssert.False(string.IsNullOrWhiteSpace(x))
Type checks
.Should().BeOfType()βAssert.True(x is Type).Should().NotBeOfType()βAssert.False(x is Type).Should().BeAssignableTo<T>()βAssert.IsAssignableFrom<T>(x)
Exceptions
.Should().Throw()βAssert.Throws().Should().NotThrow()βAssert.Nulll(Record.Exception()).Should().Throw<T>()βAssert.Throws<T>().Should().NotThrow<T>()βAssert.IsType<T>(Record.Exception()).Should().ThrowAsync()βAssert.ThrowsAsync().Should().NotThrowAsync()βAssert.Null(Record.ExceptionAsync()).Should().ThrowAsync<T>()βAssert.ThrowsAsync<T>().Should().NotThrowAsync<T>()βAssert.IsNotType<T>(Record.ExceptionAsync())subject.Invoking(x => x.Foo())/subject.Awaiting(x => x.FooAsync())β the "act" is unwrapped into() => subject.Foo().Should().Throw<T>().WithMessage("*msg*")βAssert.Contains("msg", Assert.Throws<T>(...).Message).Should().Throw<T>().WithParameterName("p")βAssert.Equal("p", Assert.Throws<T>(...).ParamName)
Numeric comparisons
.Should().BeGreaterThan()βAssert.True(x > y).Should().BeLessThan()βAssert.True(x < y).Should().BeGreaterThanOrEqualTo()βAssert.True(x >= y).Should().BeLessThanOrEqualTo()βAssert.True(x <= y).Should().BePositive()βAssert.True(x > 0).Should().BeNegative()βAssert.True(x < 0).Should().BeCloseTo()βAssert.True(x > (expected - precision) && x < (expected + precision)).Should().NotBeCloseTo()βAssert.False(x > (expected - precision) && x < (expected + precision))
Date comparisons
.Should().BeBefore()βAssert.True(x < y).Should().NotBeBefore()βAssert.False(x < y).Should().BeAfter()βAssert.True(x > y).Should().NotBeAfter()βAssert.False(x > y).Should().BeOnOrBefore()βAssert.True(x <= y).Should().NotBeOnOrBefore()βAssert.False(x <= y).Should().BeOnOrAfter()βAssert.True(x >= y).Should().NotBeOnOrAfter()βAssert.False(x >= y)
Important Note
While this tool automates a significant portion of the migration, manual review and adjustments will be needed:
- Some complex FluentAssertions may not have direct xUnit equivalents
- Custom assertion messages will need to be reformatted
- Chain assertions (using .And) will need to be split into multiple Assert statements
- Some assertions might require additional null checks or type conversions
Always review the generated code and test thoroughly after migration.
Contributing
Feel free to submit issues and pull requests but I'm not making any promises. :-)
Is this free?
Yes, it is! If you really like this and want to give something in return, donations can be made here: https://github.com/sponsors/amoerie?frequency=one-time. Thanks!
Changes from Previous Version
Adoption Assessment
Assess this package against its supported frameworks, license, maintenance signals and dependency graph before making it a project standard.
Related Guides & Workflows
Learn how to evaluate, integrate, or audit this package in your .NET project.