1. xUnit has compact API. NUnit has much more methods, attributes and syntax for fluent assertions.
Equal(2, a); // xUnit
Assert.That(a, Is.EqualTo(2)); // NUnit
2. xUnit calls constructor of test-class for each test method. In contrast, NUnit calls constructor once for all your tests.
Therefore, with NUnit you must setup your test in method, marked as [SetUp] attribute.
In xUnit following tests will pass, because tests are isolated from each other:
int _a = 3;
[Fact]
public void Test1() => Equal(3, _a++);
[Fact]
public void Test2() => Equal(3, _a++);
In NUnit following tests will fail:
int _a = 3;
[Test]
public void Test1() => Assert.That(_a++, Is.EqualTo(3));
[Test]
public void Test2() => Assert.That(_a++, Is.EqualTo(3)); // NUnit fails here
3. xUnit has more type-safe equality assert.
NUnit will sucessfully compile following code, but tests will fail:
[Test]
public void Test1()
{
var ct = new CancellationTokenSource();
Assert.That(ct, Is.EqualTo(ct.Token));
Assert.AreEqual(ct, Is.EqualTo(ct.Token));
// AreEqual works with Object type. This is type-unsafe
// public static void AreEqual(object? expected, object? actual) {...}
}
In case of xUnit these errors are not possibe. xUnit equality assert is generic by default:
[Fact]
public void Test1()
{
var ct = new CancellationTokenSource();
Equal(ct, ct.Token);
// Compile time error, Equal method is generic
// public static void Equal<T>(T expected, T actual) {...}
}