From 7528e4d1084c14748e6a2935567a3d3f31c6952e Mon Sep 17 00:00:00 2001 From: Tom Longhurst <30480171+thomhurst@users.noreply.github.com> Date: Sat, 2 May 2026 21:24:59 +0100 Subject: [PATCH] fix(xunit): keep sync throws migration --- .../XUnitMigrationAnalyzerTests.cs | 80 +++++++++++++++++++ docs/docs/migration/xunit.md | 11 +-- 2 files changed, 86 insertions(+), 5 deletions(-) diff --git a/TUnit.Analyzers.Tests/XUnitMigrationAnalyzerTests.cs b/TUnit.Analyzers.Tests/XUnitMigrationAnalyzerTests.cs index 5b86515664..e8e9cafa7f 100644 --- a/TUnit.Analyzers.Tests/XUnitMigrationAnalyzerTests.cs +++ b/TUnit.Analyzers.Tests/XUnitMigrationAnalyzerTests.cs @@ -1487,6 +1487,86 @@ public async Task MyTest() ); } + [Test] + public async Task Assert_Throws_Sync_Delegate_Stays_Sync() + { + await CodeFixer + .VerifyCodeFixAsync( + """ + {|#0:using System; + using Xunit; + + public class MyClass + { + [Fact] + public void MyTest() + { + Assert.Throws(() => ThrowException()); + } + + private void ThrowException() => throw new ArgumentException(); + }|} + """, + Verifier.Diagnostic(Rules.XunitMigration).WithLocation(0), + """ + using System; + + public class MyClass + { + [Test] + public void MyTest() + { + Assert.Throws(() => ThrowException()); + } + + private void ThrowException() => throw new ArgumentException(); + } + """, + ConfigureXUnitTest + ); + } + + [Test] + public async Task Assert_ThrowsAsync_Async_Delegate_Stays_Async() + { + await CodeFixer + .VerifyCodeFixAsync( + """ + {|#0:using System; + using System.Threading.Tasks; + using Xunit; + + public class MyClass + { + [Fact] + public async Task MyTest() + { + await Assert.ThrowsAsync(() => ThrowExceptionAsync()); + } + + private Task ThrowExceptionAsync() => Task.FromException(new ArgumentException()); + }|} + """, + Verifier.Diagnostic(Rules.XunitMigration).WithLocation(0), + """ + using System; + using System.Threading.Tasks; + + public class MyClass + { + [Test] + public async Task MyTest() + { + await Assert.ThrowsAsync(() => ThrowExceptionAsync()); + } + + private Task ThrowExceptionAsync() => Task.FromException(new ArgumentException()); + } + """, + ConfigureXUnitTest + ); + } + [Test] public async Task Assert_Throws_With_Message_Contains_Can_Be_Converted() { diff --git a/docs/docs/migration/xunit.md b/docs/docs/migration/xunit.md index e50a6f94f6..33c4a8f4db 100644 --- a/docs/docs/migration/xunit.md +++ b/docs/docs/migration/xunit.md @@ -21,7 +21,7 @@ Migrating from xUnit to TUnit can improve test execution speed. Check the [bench | `IAsyncLifetime` | `[Before(Test)]` / `[After(Test)]` | | `ITestOutputHelper` | `TestContext` parameter | | `Assert.Equal(expected, actual)` | `await Assert.That(actual).IsEqualTo(expected)` | -| `Assert.Throws(() => ...)` | `await Assert.ThrowsAsync(() => ...)` | +| `Assert.Throws(() => ...)` | `Assert.Throws(() => ...)` | ## Automated Migration with Code Fixers @@ -35,7 +35,7 @@ TUnit includes Roslyn analyzers and code fixers that automate most of the migrat - `[Trait("key", "value")]` → `[Property("key", "value")]` - `Assert.Equal(expected, actual)` → `await Assert.That(actual).IsEqualTo(expected)` - `Assert.True(condition)` → `await Assert.That(condition).IsTrue()` -- `Assert.Throws(...)` → `await Assert.ThrowsAsync(...)` +- `Assert.Throws(...)` → `Assert.Throws(...)` - `Assert.Contains(item, collection)` → `await Assert.That(collection).Contains(item)` - Test methods converted to `async Task` with `await` on assertions @@ -1022,9 +1022,9 @@ public async Task Async_Exception_Assertions() [Test] public async Task Exception_Assertions() { - await Assert.ThrowsAsync(() => ThrowsException()); + Assert.Throws(() => ThrowsException()); - var ex = await Assert.ThrowsAsync(() => ThrowsException()); + var ex = Assert.Throws(() => ThrowsException()); await Assert.That(ex.ParamName).IsEqualTo("paramName"); } @@ -1036,7 +1036,8 @@ public async Task Async_Exception_Assertions() ``` **Key Changes:** -- Both sync and async use `Assert.ThrowsAsync` in TUnit +- Sync exception assertions use `Assert.Throws` +- Async exception assertions use `Assert.ThrowsAsync` - Returned exception can be further asserted on ### Complete Example: Real-World Test Class