A simple command-line tool for migrating your code from FluentAssertions to NFluent. This tool automatically updates all using
directives and assertion statements in your C# project files (.cs
and .csproj
files) to use NFluent syntax instead of FluentAssertions.
- Replaces
using FluentAssertions
withusing NFluent
. - Converts FluentAssertions assertions to equivalent NFluent assertions (e.g.,
.Should().Be()
→.IsEqualTo()
). - Supports
.cs
and.csproj
files. - Process multiple files in a directory and subdirectories.
See the section about the supported assertions for more details.
- .NET 6.0+ SDK
- C# development environment (e.g., Visual Studio, Rider, or Visual Studio Code)
Once the project is built, you can use the tool by running the compiled executable from the command line.
-
Clone the repository:
git clone https://github.com/yourusername/fluentassertions-to-nfluent-migrator.git cd fluentassertions-to-nfluent-migrator
-
Build the project using the .NET CLI:
dotnet build -o ./output
.\output\Migrator.exe <path-to-directory>
Where is the path to the directory containing the C# project files (.cs and .csproj). The tool will process all matching files in the specified directory and its subdirectories.
While the tool runs, you'll see a message indicating the progress of the replacement, along with a spinner:
Replacement started
Processing .cs files...
Processing SomeFile.cs...|
Processing AnotherFile.cs.../
Processing YetAnotherFile.cs...-
...
Replacement complete.
Once the replacement is complete, it will output:
Replacement complete.
File Types Processed
.cs: C# source files containing FluentAssertions assertions.
.csproj: Project files that may include references to FluentAssertions.
File Content Changes
- All occurrences of using FluentAssertions are replaced with using NFluent.
- Assertions using FluentAssertions methods (e.g., .Should().Be(...)) are updated to the equivalent NFluent assertion (e.g., .IsEqualTo(...)).
Example Changes
Before:
using FluentAssertions;
public void Test()
{
var myObject = new MyClass();
myObject.Should().Be(expectedObject);
}
After:
using NFluent;
public void Test()
{
var myObject = new MyClass();
Check.That(myObject).IsEqualTo(expectedObject);
}
You can customize or extend the tool's functionality by modifying the following classes:
CsFileContentReplacer
: Contains the logic for replacing assertions in .cs files.CsProjFileContentReplacer
: Contains the logic for replacing content in .csproj files (e.g., using FluentAssertions).Program
: The entry point of the tool where file processing and updates are triggered.
Complex Expressions: In cases where assertions are deeply nested or formatted irregularly, the tool may not fully capture the exact syntax. You may need to review the resulting code to ensure correctness.
This tool is under development, some FluentAssertions assertions may not be correctly replaced yet.
Feel free to fork this repository and submit pull requests for any features or fixes you think are useful!
It's a very simple project, here is how you can add a transformation:
- Write a unit test like the following:
[Fact]
public void Should_replace_ShouldBeTrue()
{
const string fluentAssertions = "var.Should().BeTrue();";
const string nfluentEquivalent = "Check.That(var).IsTrue();";
var actual = CsFileContentReplacer.Replace(fluentAssertions);
Check.That(actual).IsEqualTo(nfluentEquivalent);
}
Add the regex to the CsFileContentReplacer.cs
to make the test pass:
// .Should().BeTrue() -> Check.That(var).IsTrue();
(@"(?<subject>\S(?:.*\S)?)\s*\.Should\(\)\s*\.BeTrue\s*\(\s*\)\s*;", "Check.That(${subject}).IsTrue();"),
And that's it!
If you never contributed to an open source project yet, It is a good opportunity to try because this project is very simple.
Here is a simple guide that demonstrate how to make a contribution for the first time.
If you have doubts, need help or anything do not hesitate to ask your questions in an issue, we will gladly provide all the help we can 😊
This document provides an overview of the migration support offered by the CsFileContentReplacer
for transitioning from FluentAssertions to NFluent in C# projects. While the tool automates the replacement of many common assertions, there are limitations, and some manual adjustments may be necessary.
The following FluentAssertions methods are currently supported and are automatically replaced by their NFluent equivalents:
FluentAssertions | NFluent |
---|---|
.Should().NotBeNull() |
Check.That(var).IsNotNull(); |
.Should().BeNull() |
Check.That(var).IsNull(); |
.Should().Be(value) |
Check.That(var).IsEqualTo(value); |
.Should().NotBe(value) |
Check.That(var).IsNotEqualTo(value); |
.Should().BeGreaterThan(value) |
Check.That(var).IsGreaterThan(value); |
.Should().BeGreaterOrEqualTo(value) |
Check.That(var).IsGreaterOrEqualTo(value); |
.Should().BeLessThan(value) |
Check.That(var).IsLessThan(value); |
.Should().BeLessOrEqualTo(value) |
Check.That(var).IsLessOrEqualTo(value); |
.Should().BeEquivalentTo(object) |
Check.That(var).HasFieldsWithSameValues(object); |
.Should().Contain(value) |
Check.That(var).Contains(value); |
.Should().NotContain(value) |
Check.That(var).Not.Contains(value); |
.Should().ContainSingle() |
Check.That(var).HasSize(1); |
.Should().OnlyContain(value) |
Check.That(var).ContainsOnlyElementsThatMatch(value); |
.Should().HaveCount(value) |
Check.That(var).HasSize(value); |
.Should().HaveSameCount(value) |
Check.That(var).HasSameSizeAs(value); |
.Should().HaveCountGreaterThan(value) |
Check.That(var).WhoseSize().IsStrictlyGreaterThan(value); |
.Should().HaveCountGreaterOrEqualTo(value) |
Check.That(var).WhoseSize().IsGreaterOrEqualThan(value); |
.Should().BeEmpty() |
Check.That(var).IsEmpty(); |
.Should().NotBeEmpty() |
Check.That(var).IsNotEmpty(); |
.Should().StartWith(value) |
Check.That(var).StartsWith(value); |
.Should().EndWith(value) |
Check.That(var).EndsWith(value); |
FluentAssertions | NFluent |
---|---|
.Should().BeEmpty() |
Check.That(var).IsEmpty(); |
.Should().NotBeEmpty() |
Check.That(var).Not.IsEmpty(); |
.Should().HaveLength(value) |
Check.That(var).HasSize(value); |
.Should().BeNullOrWhiteSpace() |
Check.That(var).IsNullOrWhiteSpace(); |
.Should().NotBeNullOrWhiteSpace() |
Check.That(var).Not.IsNullOrWhiteSpace(); |
FluentAssertions | NFluent |
---|---|
.Should().BeTrue() |
Check.That(var).IsTrue(); |
.Should().BeFalse() |
Check.That(var).IsFalse(); |
.Should().NotBeTrue() |
Check.That(var).Not.IsTrue(); |
.Should().NotBeFalse() |
Check.That(var).Not.IsFalse(); |
FluentAssertions | NFluent |
---|---|
.Should().Throw<ExceptionType>() |
Check.ThatCode(action).Throws<ExceptionType>(); |
.Should().ThrowExactly<ExceptionType>() |
Check.ThatCode(action).ThrowsExactly<ExceptionType>(); |
.Should().NotThrow() |
Check.ThatCode(action).DoesNotThrow(); |
.Should().ThrowAsync<ExceptionType>() |
Check.ThatCode(() => action()).ThrowsType(typeof(ExceptionType)); |
.Should().NotThrowAsync() |
Check.ThatCode(() => action()).DoesNotThrow(); |
.Should().Throw<ExceptionType>().WithMessage("...") |
Check.ThatCode(action).Throws<ExceptionType>().AndWhichMessage().Matches("..."); |
.Should().ThrowAsync<ExceptionType>().WithMessage("...") |
Check.ThatCode(() => action()).ThrowsType(typeof(ExceptionType)).AndWhichMessage().Matches("..."); |
FluentAssertions | NFluent |
---|---|
.Should().HaveValue() |
Check.That(var).HasValue(); |
.Should().NotHaveValue() |
Check.That(var).Not.HasValue(); |
.Should().Match(x => condition) |
Check.That(var).Matches(x => condition); |
FluentAssertions | NFluent |
---|---|
.Should().ContainKey(value) |
Check.That(var.Keys).Contains(value); |
.Should().NotContainKey(value) |
Check.That(var.Keys).Not.Contains(value); |
.Should().BeOfType<T>() |
Check.That(var).IsInstanceOfType(typeof(T)); |
.Should().BeOfType(value) |
Check.That(var).IsInstanceOfType(value); |
.Should().Equal(value) |
Check.That(var).IsEqualTo(value); |
.Should().NotEqual(value) |
Check.That(var).IsNotEqualTo(value); |
.Should().ContainSingle() |
Check.That(var).HasSize(1); |
.Should().BeNullOrEmpty() |
Check.That(var).IsNullOrEmpty(); |
.Should().NotBeNullOrEmpty() |
Check.That(var).Not.IsNullOrEmpty(); |
While the CsFileContentReplacer
automates many assertions, some complex scenarios may require manual intervention, such as:
- Unsupported Assertions: Certain FluentAssertions methods are not yet supported.
- Complex Lambda Expressions: Assertions using intricate lambda expressions may not be transformed correctly.
- Formatting: Multi-line or poorly formatted assertions might produce unexpected output.
For multi-line assertions, while the tool handles most cases, some extra spaces may appear in the output and need to be manually fixed:
Input:
complexVar.Should()
.BeEquivalentTo(
new[]
{
Id = 1,
Name = "Test"
});
Output:
Check.That(complexVar).HasFieldsWithSameValues(new[] { Id = 1, Name = "Test" });