diff --git a/Directory.Packages.props b/Directory.Packages.props
index 1573d01cff..9164feaabb 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -81,9 +81,9 @@
-
-
-
+
+
+
diff --git a/TUnit.Assertions.SourceGenerator/Generators/AssertionMethodGenerator.cs b/TUnit.Assertions.SourceGenerator/Generators/AssertionMethodGenerator.cs
index d2c023ea00..1120d2c753 100644
--- a/TUnit.Assertions.SourceGenerator/Generators/AssertionMethodGenerator.cs
+++ b/TUnit.Assertions.SourceGenerator/Generators/AssertionMethodGenerator.cs
@@ -699,7 +699,28 @@ private static void GenerateAssertConditionClassForMethod(SourceProductionContex
sourceBuilder.AppendLine();
}
- if (!attributeData.TargetType.IsValueType)
+ // Check if the method's first parameter accepts null values
+ // For static methods like string.IsNullOrEmpty(string? value), the first parameter
+ // is the value being asserted. If it's marked as nullable (NullableAnnotation.Annotated),
+ // we should skip the null check and let the method handle null values.
+ var shouldGenerateNullCheck = !attributeData.TargetType.IsValueType;
+ if (shouldGenerateNullCheck && staticMethod.Parameters.Length > 0)
+ {
+ var firstParameter = staticMethod.Parameters[0];
+ // Skip null check if the parameter explicitly accepts null (e.g., string? value)
+ if (firstParameter.NullableAnnotation == NullableAnnotation.Annotated)
+ {
+ shouldGenerateNullCheck = false;
+ }
+ // For backwards compatibility with .NET Framework where NullableAnnotation might not be set,
+ // also check for well-known methods that accept null by design
+ else if (methodName == "IsNullOrEmpty" || methodName == "IsNullOrWhiteSpace")
+ {
+ shouldGenerateNullCheck = false;
+ }
+ }
+
+ if (shouldGenerateNullCheck)
{
sourceBuilder.AppendLine(" if (actualValue is null)");
sourceBuilder.AppendLine(" {");
diff --git a/TUnit.Assertions.Tests/Bugs/Issue3422Tests.cs b/TUnit.Assertions.Tests/Bugs/Issue3422Tests.cs
new file mode 100644
index 0000000000..78e5aa843c
--- /dev/null
+++ b/TUnit.Assertions.Tests/Bugs/Issue3422Tests.cs
@@ -0,0 +1,50 @@
+namespace TUnit.Assertions.Tests.Bugs;
+
+///
+/// Tests for issue #3422: CS8620 and CS8619 warnings with object? parameters
+/// https://github.com/thomhurst/TUnit/issues/3422
+///
+public class Issue3422Tests
+{
+ [Test]
+ [Arguments(null, null)]
+ [Arguments("test", "test")]
+ [Arguments(123, 123)]
+ public async Task Assert_That_With_Object_Nullable_Parameters_Should_Not_Cause_Warnings(object? value, object? expected)
+ {
+ // This should not produce CS8620 or CS8619 warnings
+ await Assert.That(value).IsEqualTo(expected);
+ }
+
+ [Test]
+ public async Task Assert_That_Throws_With_Null_Object_Parameter_Should_Not_Cause_Warnings()
+ {
+ // This test reproduces the second scenario from issue #3422
+ object? data = null;
+ await Assert.That(() => MethodToTest(data!)).Throws();
+
+ Task