Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions TUnit.Assertions.Tests/Bugs/Issue3422Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
namespace TUnit.Assertions.Tests.Bugs;

/// <summary>
/// Tests for issue #3422: CS8620 and CS8619 warnings with object? parameters
/// https://github.com/thomhurst/TUnit/issues/3422
/// </summary>
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<ArgumentNullException>();

Task<object> MethodToTest(object value)
{
if (value is null)
throw new ArgumentNullException(nameof(value));
return Task.FromResult(new object());
}
}

[Test]
public async Task Assert_That_With_Non_Null_Object_Parameter_Should_Not_Throw()
{
// Test that when data is not null, the method executes successfully without warnings
object? data = "test";
var result = await MethodToTest(data!);

await Assert.That(result).IsNotNull();

async Task<object> MethodToTest(object value)
{
if (value is null)
throw new ArgumentNullException(nameof(value));
return await Task.FromResult(new object());
}
}
}
8 changes: 4 additions & 4 deletions TUnit.Assertions/Conditions/EqualsAssertion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace TUnit.Assertions.Conditions;
/// </summary>
public class EqualsAssertion<TValue> : Assertion<TValue>
{
private readonly TValue _expected;
private readonly TValue? _expected;
private readonly IEqualityComparer<TValue>? _comparer;
private object? _tolerance;
private readonly HashSet<Type> _ignoredTypes = new();
Expand Down Expand Up @@ -244,11 +244,11 @@ private static bool CompareDecimal(decimal actual, decimal expected, object tole
/// Gets the expected value for this equality assertion.
/// Used by extension methods like Within() to create derived assertions.
/// </summary>
public TValue Expected => _expected;
public TValue? Expected => _expected;

public EqualsAssertion(
AssertionContext<TValue> context,
TValue expected,
TValue? expected,
IEqualityComparer<TValue>? comparer = null)
: base(context)
{
Expand Down Expand Up @@ -346,7 +346,7 @@ protected override Task<AssertionResult> CheckAsync(EvaluationMetadata<TValue> m
// Standard equality comparison
var comparer = _comparer ?? EqualityComparer<TValue>.Default;

if (comparer.Equals(value!, _expected))
if (comparer.Equals(value!, _expected!))
{
return Task.FromResult(AssertionResult.Passed);
}
Expand Down
4 changes: 2 additions & 2 deletions TUnit.Assertions/Extensions/AssertionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public static class AssertionExtensions
[OverloadResolutionPriority(0)]
public static EqualsAssertion<TValue> IsEqualTo<TValue>(
this IAssertionSource<TValue> source,
TValue expected,
TValue? expected,
[CallerArgumentExpression(nameof(expected))] string? expression = null)
{
source.Context.ExpressionBuilder.Append($".IsEqualTo({expression})");
Expand All @@ -44,7 +44,7 @@ public static EqualsAssertion<TValue> IsEqualTo<TValue>(
/// </summary>
public static EqualsAssertion<TValue> EqualTo<TValue>(
this IAssertionSource<TValue> source,
TValue expected,
TValue? expected,
[CallerArgumentExpression(nameof(expected))] string? expression = null)
{
source.Context.ExpressionBuilder.Append($".EqualTo({expression})");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ namespace .Conditions
}
public class EqualsAssertion<TValue> : .<TValue>
{
public EqualsAssertion(.<TValue> context, TValue expected, .<TValue>? comparer = null) { }
public EqualsAssertion(.<TValue> context, TValue? expected, .<TValue>? comparer = null) { }
public TValue Expected { get; }
[.("Trimming", "IL2075", Justification="Tolerance comparison requires dynamic invocation of known comparer delegates")]
protected override .<.> CheckAsync(.<TValue> metadata) { }
Expand Down Expand Up @@ -1669,7 +1669,7 @@ namespace .Extensions
where TEnum : struct, { }
public static ..DoesNotHaveSameValueAsAssertion<TEnum> DoesNotHaveSameValueAs<TEnum>(this .<TEnum> source, otherEnumValue, [.("otherEnumValue")] string? expression = null)
where TEnum : struct, { }
public static .<TValue> EqualTo<TValue>(this .<TValue> source, TValue expected, [.("expected")] string? expression = null) { }
public static .<TValue> EqualTo<TValue>(this .<TValue> source, TValue? expected, [.("expected")] string? expression = null) { }
public static ..CountWrapper<TValue> HasCount<TValue>(this .<TValue> source)
where TValue : .IEnumerable { }
public static .<TValue> HasCount<TValue>(this .<TValue> source, int expectedCount, [.("expectedCount")] string? expression = null)
Expand Down Expand Up @@ -1738,7 +1738,7 @@ namespace .Extensions
public static . IsEqualTo(this .<string> source, string? expected, [.("expected")] string? expression = null) { }
public static . IsEqualTo(this .<string> source, string? expected, comparison, [.("expected")] string? expression = null) { }
[.(0)]
public static .<TValue> IsEqualTo<TValue>(this .<TValue> source, TValue expected, [.("expected")] string? expression = null) { }
public static .<TValue> IsEqualTo<TValue>(this .<TValue> source, TValue? expected, [.("expected")] string? expression = null) { }
[.(-1)]
public static .<TActual, TExpected> IsEqualTo<TActual, TExpected>(this .<TActual> source, TExpected expected, [.("expected")] string? expression = null)
where TActual : struct, <TExpected> { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ namespace .Conditions
}
public class EqualsAssertion<TValue> : .<TValue>
{
public EqualsAssertion(.<TValue> context, TValue expected, .<TValue>? comparer = null) { }
public EqualsAssertion(.<TValue> context, TValue? expected, .<TValue>? comparer = null) { }
public TValue Expected { get; }
[.("Trimming", "IL2075", Justification="Tolerance comparison requires dynamic invocation of known comparer delegates")]
protected override .<.> CheckAsync(.<TValue> metadata) { }
Expand Down Expand Up @@ -1669,7 +1669,7 @@ namespace .Extensions
where TEnum : struct, { }
public static ..DoesNotHaveSameValueAsAssertion<TEnum> DoesNotHaveSameValueAs<TEnum>(this .<TEnum> source, otherEnumValue, [.("otherEnumValue")] string? expression = null)
where TEnum : struct, { }
public static .<TValue> EqualTo<TValue>(this .<TValue> source, TValue expected, [.("expected")] string? expression = null) { }
public static .<TValue> EqualTo<TValue>(this .<TValue> source, TValue? expected, [.("expected")] string? expression = null) { }
public static ..CountWrapper<TValue> HasCount<TValue>(this .<TValue> source)
where TValue : .IEnumerable { }
public static .<TValue> HasCount<TValue>(this .<TValue> source, int expectedCount, [.("expectedCount")] string? expression = null)
Expand Down Expand Up @@ -1727,7 +1727,7 @@ namespace .Extensions
public static . IsEqualTo(this .<long> source, long expected, [.("expected")] string? expression = null) { }
public static . IsEqualTo(this .<string> source, string? expected, [.("expected")] string? expression = null) { }
public static . IsEqualTo(this .<string> source, string? expected, comparison, [.("expected")] string? expression = null) { }
public static .<TValue> IsEqualTo<TValue>(this .<TValue> source, TValue expected, [.("expected")] string? expression = null) { }
public static .<TValue> IsEqualTo<TValue>(this .<TValue> source, TValue? expected, [.("expected")] string? expression = null) { }
public static .<TActual, TExpected> IsEqualTo<TActual, TExpected>(this .<TActual> source, TExpected expected, [.("expected")] string? expression = null)
where TActual : struct, <TExpected> { }
public static .<TActual, TExpected> IsEqualTo<TActual, TExpected>(this .<TActual?> source, TExpected expected, [.("expected")] string? expression = null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ namespace .Conditions
}
public class EqualsAssertion<TValue> : .<TValue>
{
public EqualsAssertion(.<TValue> context, TValue expected, .<TValue>? comparer = null) { }
public EqualsAssertion(.<TValue> context, TValue? expected, .<TValue>? comparer = null) { }
public TValue Expected { get; }
[.("Trimming", "IL2075", Justification="Tolerance comparison requires dynamic invocation of known comparer delegates")]
protected override .<.> CheckAsync(.<TValue> metadata) { }
Expand Down Expand Up @@ -1669,7 +1669,7 @@ namespace .Extensions
where TEnum : struct, { }
public static ..DoesNotHaveSameValueAsAssertion<TEnum> DoesNotHaveSameValueAs<TEnum>(this .<TEnum> source, otherEnumValue, [.("otherEnumValue")] string? expression = null)
where TEnum : struct, { }
public static .<TValue> EqualTo<TValue>(this .<TValue> source, TValue expected, [.("expected")] string? expression = null) { }
public static .<TValue> EqualTo<TValue>(this .<TValue> source, TValue? expected, [.("expected")] string? expression = null) { }
public static ..CountWrapper<TValue> HasCount<TValue>(this .<TValue> source)
where TValue : .IEnumerable { }
public static .<TValue> HasCount<TValue>(this .<TValue> source, int expectedCount, [.("expectedCount")] string? expression = null)
Expand Down Expand Up @@ -1738,7 +1738,7 @@ namespace .Extensions
public static . IsEqualTo(this .<string> source, string? expected, [.("expected")] string? expression = null) { }
public static . IsEqualTo(this .<string> source, string? expected, comparison, [.("expected")] string? expression = null) { }
[.(0)]
public static .<TValue> IsEqualTo<TValue>(this .<TValue> source, TValue expected, [.("expected")] string? expression = null) { }
public static .<TValue> IsEqualTo<TValue>(this .<TValue> source, TValue? expected, [.("expected")] string? expression = null) { }
[.(-1)]
public static .<TActual, TExpected> IsEqualTo<TActual, TExpected>(this .<TActual> source, TExpected expected, [.("expected")] string? expression = null)
where TActual : struct, <TExpected> { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,7 @@ namespace .Conditions
}
public class EqualsAssertion<TValue> : .<TValue>
{
public EqualsAssertion(.<TValue> context, TValue expected, .<TValue>? comparer = null) { }
public EqualsAssertion(.<TValue> context, TValue? expected, .<TValue>? comparer = null) { }
public TValue Expected { get; }
protected override .<.> CheckAsync(.<TValue> metadata) { }
protected override string GetExpectation() { }
Expand Down Expand Up @@ -1574,7 +1574,7 @@ namespace .Extensions
where TEnum : struct, { }
public static ..DoesNotHaveSameValueAsAssertion<TEnum> DoesNotHaveSameValueAs<TEnum>(this .<TEnum> source, otherEnumValue, [.("otherEnumValue")] string? expression = null)
where TEnum : struct, { }
public static .<TValue> EqualTo<TValue>(this .<TValue> source, TValue expected, [.("expected")] string? expression = null) { }
public static .<TValue> EqualTo<TValue>(this .<TValue> source, TValue? expected, [.("expected")] string? expression = null) { }
public static ..CountWrapper<TValue> HasCount<TValue>(this .<TValue> source)
where TValue : .IEnumerable { }
public static .<TValue> HasCount<TValue>(this .<TValue> source, int expectedCount, [.("expectedCount")] string? expression = null)
Expand Down Expand Up @@ -1622,7 +1622,7 @@ namespace .Extensions
public static . IsEqualTo(this .<long> source, long expected, [.("expected")] string? expression = null) { }
public static . IsEqualTo(this .<string> source, string? expected, [.("expected")] string? expression = null) { }
public static . IsEqualTo(this .<string> source, string? expected, comparison, [.("expected")] string? expression = null) { }
public static .<TValue> IsEqualTo<TValue>(this .<TValue> source, TValue expected, [.("expected")] string? expression = null) { }
public static .<TValue> IsEqualTo<TValue>(this .<TValue> source, TValue? expected, [.("expected")] string? expression = null) { }
public static .<TActual, TExpected> IsEqualTo<TActual, TExpected>(this .<TActual> source, TExpected expected, [.("expected")] string? expression = null)
where TActual : struct, <TExpected> { }
public static .<TActual, TExpected> IsEqualTo<TActual, TExpected>(this .<TActual?> source, TExpected expected, [.("expected")] string? expression = null)
Expand Down
Loading