Skip to main content

xUnit

The fixer rewrites each Xunit.Assert.* call into the corresponding Expect.That(actual).<Assertion>(expected) form. The argument order in xUnit (Assert.Equal(expected, actual)) is swapped to match the "actual first" convention of aweXpect.

// Before (xUnit)
Assert.Equal(expected, actual);
Assert.Throws<ArgumentException>(callback);

// After (aweXpect)
await Expect.That(actual).IsEqualTo(expected);
await Expect.That(callback).ThrowsExactly<ArgumentException>();

A note in the last column marks a rewrite that behaves differently in some cases; it links to the matching entry under Behavioural differences.

Basic​

xUnit constructRewritten to
Assert.Fail("msg")Fail.Test("msg")
Assert.Skip("msg")Skip.Test("msg")
Assert.Null(subject)Expect.That(subject).IsNull()
Assert.NotNull(subject)Expect.That(subject).IsNotNull()
Assert.Same(expected, actual)Expect.That(actual).IsSameAs(expected)
Assert.NotSame(expected, actual)Expect.That(actual).IsNotSameAs(expected)

Booleans​

xUnit constructRewritten to
Assert.True(subject)Expect.That(subject).IsTrue()
Assert.False(subject)Expect.That(subject).IsFalse()
Assert.True(subject, "msg")Expect.That(subject).IsTrue().Because("msg")
Assert.False(subject, "msg")Expect.That(subject).IsFalse().Because("msg")

Equality​

xUnit constructRewritten toNote
Assert.Equal(expected, actual)Expect.That(actual).IsEqualTo(expected)collections, numbers, kind
Assert.NotEqual(expected, actual)Expect.That(actual).IsNotEqualTo(expected)
Assert.Equal(expected, actual, tolerance) (double / float / TimeSpan)Expect.That(actual).IsEqualTo(expected).Within(tolerance)kind
Assert.NotEqual(expected, actual, tolerance) (double / float)Expect.That(actual).IsNotEqualTo(expected).Within(tolerance)
Assert.Equal(expected, actual, precision) (double / float / decimal)Expect.That(Math.Round(actual, precision)).IsEqualTo(Math.Round(expected, precision))
Assert.NotEqual(expected, actual, precision) (double / float / decimal)Expect.That(Math.Round(actual, precision)).IsNotEqualTo(Math.Round(expected, precision))

The precision of xUnit rounds both values to the given number of decimal places, which no tolerance can express, so the rewrite rounds them the same way. A MidpointRounding argument is passed on to Math.Round, and a using for System is added when necessary. Any other additional argument, such as a comparer, ignoreCase: true or a StringComparison on Assert.Contains, leaves the assertion for manual migration.

Strings​

xUnit constructRewritten toNote
Assert.Contains(expected, actual)Expect.That(actual).Contains(expected)empty
Assert.DoesNotContain(unexpected, actual)Expect.That(actual).DoesNotContain(unexpected)null
Assert.StartsWith(expected, actual)Expect.That(actual).StartsWith(expected)empty
Assert.EndsWith(expected, actual)Expect.That(actual).EndsWith(expected)empty
Assert.Empty(actual)Expect.That(actual).IsEmpty()
Assert.NotEmpty(actual)Expect.That(actual).IsNotEmpty()

Collections​

xUnit constructRewritten to
Assert.Distinct(actual)Expect.That(actual).All().AreUnique()
Assert.Contains(expected, collection)Expect.That(collection).Contains(expected)
Assert.Contains(collection, predicate)Expect.That(collection).Contains(predicate)
Assert.DoesNotContain(unexpected, collection)Expect.That(collection).DoesNotContain(unexpected)
Assert.Contains(key, dictionary)Expect.That(dictionary).ContainsKey(key)
Assert.DoesNotContain(key, dictionary)Expect.That(dictionary).DoesNotContainKey(key)
Assert.Empty(collection)Expect.That(collection).IsEmpty()
Assert.NotEmpty(collection)Expect.That(collection).IsNotEmpty()

Exceptions​

xUnit constructRewritten to
Assert.Throws<T>(callback) / ThrowsAsync<T>(callback)Expect.That(callback).ThrowsExactly<T>()
Assert.Throws<T>(paramName, callback) / ThrowsAsync<T>(...)Expect.That(callback).ThrowsExactly<T>().WithParamName(paramName)
Assert.Throws(typeof(T), callback)Expect.That(callback).ThrowsExactly(typeof(T))
Assert.ThrowsAny<T>(callback) / ThrowsAnyAsync<T>(callback)Expect.That(callback).Throws<T>()

Types​

xUnit constructRewritten toNote
Assert.IsAssignableFrom<T>(actual)Expect.That(actual).Is<T>()
Assert.IsNotAssignableFrom<T>(actual)Expect.That(actual).IsNot<T>()null
Assert.IsType<T>(actual)Expect.That(actual).IsExactly<T>()
Assert.IsType<T>(actual, exactMatch: false)Expect.That(actual).Is<T>()
Assert.IsNotType<T>(actual)Expect.That(actual).IsNotExactly<T>()null
Assert.IsNotType<T>(actual, exactMatch: false)Expect.That(actual).IsNot<T>()null

The non-generic overloads (Assert.IsType(typeof(T), actual) etc.) are migrated to the matching non-generic aweXpect form. An exactMatch argument that is not a true or false literal leaves the assertion for manual migration.

Behavioural differences​

Compared with xUnit 3, a few rewritten assertions pass or fail for different inputs than the original. These follow from the rules listed under Behavioural differences for FluentAssertions.

Nested collections and sets​

Assert.Equal compares nested collections item by item and a set without regard to order. IsEqualTo compares the items of a collection with their Equals and in the order in which the collection enumerates them, also for a HashSet<T>. Use equivalency for nested collections and InAnyOrder() for sets:

await Expect.That(actual).IsEquivalentTo(expected);
await Expect.That(actualSet).IsEqualTo(expectedSet).InAnyOrder();

Numbers of different types​

Assert.Equal((object)1, (object)1L) fails, while IsEqualTo on an object compares numbers by value and passes.

DateTime kinds​

Assert.Equal ignores the kind of a DateTime, with or without a precision. aweXpect does not compare a DateTimeKind.Local value with a DateTimeKind.Utc value, because the same ticks describe different instants, so the rewrite fails for such a pair. Convert the values with ToUniversalTime() first.

Empty substrings throw​

Assert.Contains("", actual), Assert.StartsWith("", actual) and Assert.EndsWith("", actual) pass for every string. The rewrites throw an ArgumentException, because an expectation that cannot fail checks nothing.

Negated inspections fail for null​

Assert.DoesNotContain("x", actual) passes for a null string, and Assert.IsNotType<T>(null) and Assert.IsNotAssignableFrom<T>(null) pass as well. The rewrites fail, because null has no content or type to inspect. Allow null explicitly where it is acceptable:

await Expect.That(actual).IsNull().Or.DoesNotContain("x");