Skip to content

Fix Arg.IsNull<T> and Arg.IsNotNull<T> to support nullable value types#5366

Merged
thomhurst merged 5 commits intomainfrom
fix/arg-isnull-nullable-constraint
Apr 4, 2026
Merged

Fix Arg.IsNull<T> and Arg.IsNotNull<T> to support nullable value types#5366
thomhurst merged 5 commits intomainfrom
fix/arg-isnull-nullable-constraint

Conversation

@thomhurst
Copy link
Copy Markdown
Owner

@thomhurst thomhurst commented Apr 4, 2026

Summary

  • Removed the where T : class? constraint from Arg.IsNull<T>() and Arg.IsNotNull<T>()
  • This fixes CS8620/CS8634 warnings when using nullable reference types (e.g. string?)
  • This also adds support for nullable value types (e.g. int?) — previously a gap where users couldn't use these matchers for methods with int?, bool?, etc. parameters
  • The underlying matchers (NullMatcher<T>, NotNullMatcher<T>) already handled nullable types correctly via is null / is not null

Fixes #5360

Test plan

  • Arg.IsNull<string?>() compiles without warnings
  • Arg.IsNotNull<string?>() compiles without warnings
  • Arg.IsNull<string>() existing usage still works
  • Arg.IsNull<int?>() now compiles and matches null correctly
  • Arg.IsNotNull<int?>() now compiles and matches non-null correctly
  • TUnit.Mocks builds cleanly across all target frameworks

Relax generic constraint from `class` to `class?` so nullable reference
types (e.g. `string?`) can be used without CS8620/CS8634 warnings.

Fixes #5360
Copy link
Copy Markdown
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

Summary

This is a clean, minimal, and correct fix. The change from where T : class to where T : class? is exactly the right approach to eliminate CS8620/CS8634 warnings when using nullable reference types with Arg.IsNull<T>() and Arg.IsNotNull<T>().

Analysis

The fix is correct. In C# nullable-aware contexts:

  • where T : class — constrains to non-nullable reference types only, causing the compiler to warn when string? is passed as the type argument
  • where T : class? — constrains to reference types (both nullable and non-nullable), which is what these methods actually need

The underlying matchers (NullMatcher<T> and NotNullMatcher<T>) already use T? in their Matches signatures, confirming they were designed with nullable intent. The constraint was simply lagging behind.

One Thing to Consider (not a blocker)

Currently neither IsNull nor IsNotNull supports Nullable<T> value types (e.g. int?). With where T : class?, Arg.IsNull<int?>() still won't compile because int? (Nullable<int>) is a struct. This is a pre-existing gap and outside the scope of this PR, but worth noting as a potential follow-up issue — users with methods like void Foo(int? x) can't use these matchers today.

If support for nullable value types is desirable in the future, a separate overload or unconstrained generic with runtime null check would be the path forward.

Verdict

The change is backward-compatible, fixes a real developer-experience issue with no side effects, and the PR description is clear and accurate. Approved.

@codacy-production
Copy link
Copy Markdown

codacy-production bot commented Apr 4, 2026

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 23 complexity

Metric Results
Complexity 23

View in Codacy

TIP This summary will be updated as you push new changes. Give us feedback

Remove the `where T : class?` constraint so these matchers work with
nullable value types such as `int?`. Users can now write
`Arg.IsNull<int?>()` for methods with nullable value-type parameters.
@thomhurst thomhurst changed the title Fix Arg.IsNull<T> and Arg.IsNotNull<T> nullability warnings Fix Arg.IsNull<T> and Arg.IsNotNull<T> to support nullable value types Apr 4, 2026
@claude
Copy link
Copy Markdown
Contributor

claude bot commented Apr 4, 2026

Updated Code Review (Follow-up)

This is an update to my earlier review. The PR has evolved significantly from what I initially analyzed — the constraint change is more substantial than where T : classwhere T : class?.

What Changed

The final implementation completely removes the generic constraint from IsNull<T> and IsNotNull<T>:

// Before
public static Arg<T> IsNull<T>() where T : class => new(new NullMatcher<T>());
public static Arg<T> IsNotNull<T>() where T : class => new(new NotNullMatcher<T>());

// After (this PR)
public static Arg<T> IsNull<T>() => new(new NullMatcher<T>());
public static Arg<T> IsNotNull<T>() => new(new NotNullMatcher<T>());

This is a broader change than described in the PR summary (which only mentions relaxing to where T : class?). Removing the constraint entirely also allows non-nullable value types like int, bool, Guid, etc.

Correctness Analysis

For Nullable<T> (e.g. int?): Works correctly. The NullMatcher<T>.Matches(T? value) => value is null and the object? overload both handle this correctly. The new tests confirm this path. ✓

For non-nullable value types (e.g. int, bool): Arg.IsNull<int>() will now compile but will always return false — a value type can never be null. Similarly Arg.IsNotNull<int>() will always return true. These aren't runtime errors, but they are semantically vacuous/misleading usages.

This isn't necessarily a blocking concern (users shouldn't be calling IsNull<int>()), but it's worth deciding whether to:

  1. Accept this as a "you get what you ask for" situation (the current implicit choice), or
  2. Add a where T : class? constraint instead of no constraint, combined with a separate overload for nullable value types

Option 2 — More Precise API (optional follow-up)

If you want to prevent the vacuous IsNull<int>() usage from compiling, a two-overload approach would be more precise:

// Overload for reference types (including nullable reference types)
public static Arg<T> IsNull<T>() where T : class? => new(new NullMatcher<T>());

// Overload for nullable value types  
public static Arg<T> IsNull<T>() where T : struct => new(new NullMatcher<T?>());  // returns Arg<T?> implicitly

However, this adds complexity and is arguably over-engineering for a mocking DSL. The current unconstrained approach is pragmatic and correct for all realistic use cases.

Tests

The two new tests (Arg_IsNull_Matches_Null_Nullable_Value_Type and Arg_IsNotNull_Matches_NonNull_Nullable_Value_Type) correctly exercise the new int? path and cover both the null-matches and non-null-does-not-match cases. The INullableValueConsumer interface is correctly placed in BasicMockTests.cs alongside the other shared test interfaces.

One minor note: consumer.Process(0) is a good explicit inclusion in the IsNotNull test — it verifies that 0 (falsy but not null) is matched, which is an easy edge case to miss.

Verdict

The change is correct and backward-compatible. The PR description understates what was done (the constraint is fully removed, not just relaxed to class?), but the implementation and tests are sound. The "always false/true for non-nullable value types" behavior is a theoretical concern but not a real-world problem for a mocking library.

My previous comment flagging nullable value type support as a future gap has been addressed by this PR. Approved.

…ue types

Arg.IsNull<int>() and Arg.IsNotNull<int>() compile but are semantically
vacuous — a non-nullable value type can never be null. TM005 warns at
the call site and suggests using the nullable form (e.g. int?) instead.
Copy link
Copy Markdown
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This is a clean, well-thought-out fix. The approach of removing the constraint + adding a Roslyn analyzer to catch the now-possible-but-meaningless case is the right architectural pattern — better than keeping a compile-time constraint that over-restricts valid usage.

What's Good

  • Constraint removal is correct: The underlying NullMatcher<T> and NotNullMatcher<T> already use is null / is not null pattern matching, which handles Nullable<T> correctly at runtime. No changes needed there.
  • Analyzer correctness: The OriginalDefinition.SpecialType == SpecialType.System_Nullable_T check correctly distinguishes Nullable<T> (a value type that IS nullable) from plain structs. This is the right way to do this in Roslyn.
  • Namespace hierarchy match in IsArgNullMethod is robust — it won't accidentally trigger on a user-defined Arg class that happens to have an IsNull method.
  • Test coverage is solid across the expected happy/sad paths.

Issues to Address

1. TM005 is out of numerical order in Rules.cs

TM005 is declared before TM004, which breaks the numeric ordering convention the file otherwise follows. This is a minor thing but makes it harder to navigate as more rules accumulate.

2. Missing analyzer test: nullable reference type (string?)

The analyzer tests cover string (non-nullable reference) but not string? (nullable reference type). Reference types with the nullable annotation (?) are still reference types — IsValueType is false for them — so the analyzer correctly skips them. But since string? was specifically called out in the PR description as a scenario that previously caused CS8620/CS8634 warnings, it's worth adding an explicit "does not report" test to lock in this behavior:

3. INullableValueConsumer is defined in BasicMockTests.cs but used in ArgumentMatcherTests.cs

The file-level comment in BasicMockTests.cs says "Test interfaces used across mock tests", which is a reasonable home for shared interfaces. But this creates an implicit coupling — someone reading ArgumentMatcherTests.cs needs to hunt for where INullableValueConsumer comes from. Consider either:

  • Moving it to a dedicated TestInterfaces.cs file (mirrors the existing comment intent), or
  • Keeping it in BasicMockTests.cs is acceptable since the file already serves as a shared interface container.

Not a blocker, just worth being intentional about.


Nice-to-Have (Not Blocking)

A code fix provider paired with TM005 that auto-suggests appending ? (e.g., changing Arg.IsNull<int>()Arg.IsNull<int?>()) would significantly improve DX. Not required for this PR, but worth a follow-up issue.


Overall this is a solid fix. The two things worth addressing before merge are the rule ordering in Rules.cs (trivial) and the nullable reference type analyzer test gap (important for regression protection).

Copy link
Copy Markdown
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This is a clean, well-thought-out fix. The approach of removing the constraint + adding a Roslyn analyzer to catch the now-possible-but-meaningless case is the right architectural pattern — better than keeping a compile-time constraint that over-restricts valid usage.

What's Good

  • Constraint removal is correct: The underlying NullMatcher<T> and NotNullMatcher<T> already use is null / is not null pattern matching, which handles Nullable<T> correctly at runtime. No changes needed there.
  • Analyzer correctness: The OriginalDefinition.SpecialType == SpecialType.System_Nullable_T check correctly distinguishes Nullable<T> (a value type that IS nullable) from plain structs. This is the right Roslyn idiom.
  • Namespace hierarchy match in IsArgNullMethod is robust — it won't accidentally trigger on a user-defined Arg class that happens to have an IsNull method.
  • Test coverage is solid across the expected happy/sad paths.

Issues to Address

1. TM005 is out of numerical order in Rules.cs

TM005 is declared before TM004, breaking the numeric ordering convention the file otherwise follows. As more rules accumulate this makes navigation harder.

Current order: TM001, TM002, TM003, TM005, TM004
Expected order: TM001, TM002, TM003, TM004, TM005

2. Missing analyzer test: nullable reference type (string?)

The analyzer tests cover string (non-nullable reference type) but not string? (nullable reference type). Reference types with the ? annotation still have IsValueType == false, so the analyzer correctly skips them — but since string? was specifically called out in the PR description as a previously-broken scenario (CS8620/CS8634), an explicit "does not report" test would lock in this behavior:

[Test]
public async Task IsNull_With_Nullable_Reference_Type_Does_Not_Report()
{
    await Verifier.VerifyAnalyzerAsync(
        ArgStub + """

        #nullable enable
        public class TestClass
        {
            public void Test()
            {
                TUnit.Mocks.Arguments.Arg.IsNull<string?>();
            }
        }
        """
    );
}

3. INullableValueConsumer is defined in BasicMockTests.cs but used in ArgumentMatcherTests.cs

The existing comment at the top of BasicMockTests.cs describes it as a home for "Test interfaces used across mock tests", which is reasonable. But this creates an implicit dependency — readers of ArgumentMatcherTests.cs need to hunt for where INullableValueConsumer is declared. A dedicated TestInterfaces.cs would make this explicit. Not a blocker — just worth being intentional about.


Nice-to-Have (Not Blocking)

A code fix provider paired with TM005 that auto-suggests appending ? (e.g., Arg.IsNull<int>()Arg.IsNull<int?>()) would improve DX. Worth a follow-up issue.


Overall this is a solid fix. The two things most worth addressing before merge are the rule ordering in Rules.cs (trivial) and the missing nullable reference type analyzer test (important for regression protection given the PR's stated motivation).

Move TM005 after TM004 to restore numeric ordering in Rules.cs.
Add explicit tests that Arg.IsNull/IsNotNull<string?>() does not
trigger TM005, locking in the nullable reference type behaviour.
Copy link
Copy Markdown
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This is a well-executed fix. The approach is correct: remove the overly-restrictive where T : class constraint (the runtime matchers already worked via is null/is not null), then compensate with a Roslyn analyzer to catch the genuinely broken case.

What's Good

Clean runtime fixNullMatcher<T> and NotNullMatcher<T> already used value is null/value is not null pattern matching which handles both reference and nullable value types correctly. The constraint was purely a compile-time restriction that didn't reflect reality.

Analyzer as compensation — Adding TM005 to warn on Arg.IsNull<int>() (non-nullable struct, can never be null) is exactly the right trade-off. Users get the runtime flexibility they need, but still get guidance when they've made a logical error.

Namespace chain check in IsArgNullMethod — The full namespace walk is the correct Roslyn approach for identifying a specific well-known method without taking a package reference.

Test coverage — Both the integration tests and analyzer tests cover the full matrix: non-nullable struct (warns), nullable value type (no warn), reference type (no warn), nullable reference type (no warn).

Minor Issues

INullableValueConsumer placed in the wrong file — The interface is defined in BasicMockTests.cs but is only used in ArgumentMatcherTests.cs. This creates a subtle coupling between unrelated test files. Consider moving it to ArgumentMatcherTests.cs (where it's consumed) or a shared TestInterfaces.cs file.

TM005 missing description parameter — The other rules (TM001–TM004) don't have it either, but it's worth noting that a description string gives IDE tooling richer hover text and is surfaced in dotnet_diagnostic suppression docs. Not a blocker, just a gap consistent with the rest of the file.

Behavior note (not a bug): When T = int (non-nullable struct, triggering TM005), NullMatcher<int>.Matches(int? value) will be called and will always return false. The diagnostic makes this a warning, not an error. If you want to prevent the "silent never-matches" case more strictly, TM005 could be DiagnosticSeverity.Error. But Warning is defensible if you want to avoid breaking existing code during upgrade.

Summary

Solid implementation. The single actionable item is relocating INullableValueConsumer to ArgumentMatcherTests.cs. Everything else is well-reasoned.

…tions

- Move INullableValueConsumer to ArgumentMatcherTests.cs where it is used
- Promote TM005 to DiagnosticSeverity.Error (non-nullable IsNull/IsNotNull
  is always wrong, not just suspicious)
- Add description strings to all rules (TM001-TM005) for richer IDE hover
  text and dotnet_diagnostic suppression documentation
@thomhurst thomhurst enabled auto-merge (squash) April 4, 2026 12:51
Copy link
Copy Markdown
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated Code Review

This is a follow-up to my earlier reviews. The PR now fully addresses the concern I raised — let me document the final state.

Previous Concern: Addressed

My prior review flagged that removing where T : class would allow semantically vacuous usages like Arg.IsNull<int>() (which can never match since int is never null). The new ArgIsNullNonNullableAnalyzer (TM005) directly closes that gap with a compile-time error.

What's New In This Version

TM005 Analyzer (ArgIsNullNonNullableAnalyzer.cs) — correct and well-structured:

  • Fires on SyntaxKind.InvocationExpression — efficient, avoids broad symbol walks
  • IsArgNullMethod uses full namespace qualification (TUnit.Mocks.Arguments.Arg) — avoids false positives from other Arg classes
  • Correctly excludes Nullable<T> via OriginalDefinition.SpecialType == SpecialType.System_Nullable_T
  • DiagnosticSeverity.Error is appropriate — calling Arg.IsNull<int>() is always wrong

Analyzer Tests (ArgIsNullNonNullableAnalyzerTests.cs) — comprehensive coverage:

  • Reports for non-nullable struct (int, bool)
  • Does not report for int?, string, string?
  • The ArgStub correctly reflects the unconstrained signature — good test hygiene

TM001–TM004 descriptions added — small but welcome improvement for IDE tooltips and docs.

One Minor Observation

In the ArgStub used by analyzer tests:

public struct Arg<T> { }

The real Arg<T> is presumably a struct or class — this is fine for analyzer testing since the analyzer only inspects the method symbol, not the return type. Just worth noting that the stub doesn't need to exactly match the real type; it only needs to satisfy the namespace/method/generic-arity check in IsArgNullMethod.

Verdict

The implementation is correct, complete, and well-tested. The three-part solution (constraint removal + runtime matchers + TM005 analyzer) is the right architecture:

  1. Constraint removal — enables int? usage that was previously blocked
  2. Runtime matchers — already handled null checks correctly via is null / is not null
  3. TM005 analyzer — prevents the nonsensical Arg.IsNull<int>() usage from silently compiling

All concerns from previous reviews have been addressed. Approved.

@thomhurst thomhurst merged commit 15f14e2 into main Apr 4, 2026
15 checks passed
github-actions bot pushed a commit to IntelliTect/CodingGuidelines that referenced this pull request Apr 6, 2026
Updated [TUnit.Core](https://github.com/thomhurst/TUnit) from 1.23.7 to
1.28.7.

<details>
<summary>Release notes</summary>

_Sourced from [TUnit.Core's
releases](https://github.com/thomhurst/TUnit/releases)._

## 1.28.7

<!-- Release notes generated using configuration in .github/release.yml
at v1.28.7 -->

## What's Changed
### Other Changes
* fix: prevent StringBuilder race in console interceptor during parallel
tests by @​thomhurst in thomhurst/TUnit#5414
### Dependencies
* chore(deps): update tunit to 1.28.5 by @​thomhurst in
thomhurst/TUnit#5415


**Full Changelog**:
thomhurst/TUnit@v1.28.5...v1.28.7

## 1.28.5

<!-- Release notes generated using configuration in .github/release.yml
at v1.28.5 -->

## What's Changed
### Other Changes
* perf: eliminate redundant builds in CI pipeline by @​thomhurst in
thomhurst/TUnit#5405
* perf: eliminate store.ToArray() allocation on mock behavior execution
hot path by @​thomhurst in thomhurst/TUnit#5409
* fix: omit non-class/struct constraints on explicit interface mock
implementations by @​thomhurst in
thomhurst/TUnit#5413
### Dependencies
* chore(deps): update tunit to 1.28.0 by @​thomhurst in
thomhurst/TUnit#5406


**Full Changelog**:
thomhurst/TUnit@v1.28.0...v1.28.5

## 1.28.0

<!-- Release notes generated using configuration in .github/release.yml
at v1.28.0 -->

## What's Changed
### Other Changes
* fix: resolve build warnings in solution by @​thomhurst in
thomhurst/TUnit#5386
* Perf: Optimize MockEngine hot paths (~30-42% faster) by @​thomhurst in
thomhurst/TUnit#5391
* Move Playwright install into pipeline module by @​thomhurst in
thomhurst/TUnit#5390
* perf: optimize solution build performance by @​thomhurst in
thomhurst/TUnit#5393
* perf: defer per-class JIT via lazy test registration + parallel
resolution by @​thomhurst in
thomhurst/TUnit#5395
* Perf: Generate typed HandleCall<T1,...> overloads to eliminate
argument boxing by @​thomhurst in
thomhurst/TUnit#5399
* perf: filter generated attributes to TUnit-related types only by
@​thomhurst in thomhurst/TUnit#5402
* fix: generate valid mock class names for generic interfaces with
non-built-in type args by @​thomhurst in
thomhurst/TUnit#5404
### Dependencies
* chore(deps): update tunit to 1.27.0 by @​thomhurst in
thomhurst/TUnit#5392
* chore(deps): update dependency path-to-regexp to v8 by @​thomhurst in
thomhurst/TUnit#5378


**Full Changelog**:
thomhurst/TUnit@v1.27.0...v1.28.0

## 1.27.0

<!-- Release notes generated using configuration in .github/release.yml
at v1.27.0 -->

## What's Changed
### Other Changes
* Fix Dependabot security vulnerabilities in docs site by @​thomhurst in
thomhurst/TUnit#5372
* fix: use 0.0.0-scrubbed sentinel version in snapshot scrubber to avoid
false Dependabot alerts by @​thomhurst in
thomhurst/TUnit#5374
* Speed up Engine.Tests by removing ProcessorCount parallelism cap by
@​thomhurst in thomhurst/TUnit#5379
* ci: add concurrency groups to cancel redundant workflow runs by
@​thomhurst in thomhurst/TUnit#5373
* Add scope-aware initialization and disposal OpenTelemetry spans to
trace timeline and HTML report by @​Copilot in
thomhurst/TUnit#5339
* Add WithInnerExceptions() for fluent AggregateException assertion
chaining by @​thomhurst in thomhurst/TUnit#5380
* Drop net6.0 and net7.0 TFMs, keep net8.0+ and netstandard2.x by
@​thomhurst in thomhurst/TUnit#5387
* Remove all [Obsolete] members and migrate callers by @​thomhurst in
thomhurst/TUnit#5384
* Add AssertionResult.Failed overload that accepts an Exception by
@​thomhurst in thomhurst/TUnit#5388
### Dependencies
* chore(deps): update dependency mockolate to 2.3.0 by @​thomhurst in
thomhurst/TUnit#5370
* chore(deps): update tunit to 1.25.0 by @​thomhurst in
thomhurst/TUnit#5371
* chore(deps): update dependency minimatch to v9.0.9 by @​thomhurst in
thomhurst/TUnit#5375
* chore(deps): update dependency path-to-regexp to v0.2.5 by @​thomhurst
in thomhurst/TUnit#5376
* chore(deps): update dependency minimatch to v10 by @​thomhurst in
thomhurst/TUnit#5377
* chore(deps): update dependency picomatch to v4 by @​thomhurst in
thomhurst/TUnit#5382
* chore(deps): update dependency svgo to v4 by @​thomhurst in
thomhurst/TUnit#5383
* chore(deps): update dependency path-to-regexp to v1 [security] by
@​thomhurst in thomhurst/TUnit#5385


**Full Changelog**:
thomhurst/TUnit@v1.25.0...v1.27.0

## 1.25.0

<!-- Release notes generated using configuration in .github/release.yml
at v1.25.0 -->

## What's Changed
### Other Changes
* Fix missing `default` constraint on explicit interface implementations
with unconstrained generics by @​thomhurst in
thomhurst/TUnit#5363
* feat(mocks): add ReturnsAsync typed factory overload with method
parameters by @​thomhurst in
thomhurst/TUnit#5367
* Fix Arg.IsNull<T> and Arg.IsNotNull<T> to support nullable value types
by @​thomhurst in thomhurst/TUnit#5366
* refactor(mocks): use file-scoped types for generated implementation
details by @​thomhurst in thomhurst/TUnit#5369
* Compress HTML report JSON data and minify CSS by @​thomhurst in
thomhurst/TUnit#5368
### Dependencies
* chore(deps): update tunit to 1.24.31 by @​thomhurst in
thomhurst/TUnit#5356
* chore(deps): update dependency mockolate to 2.2.0 by @​thomhurst in
thomhurst/TUnit#5357
* chore(deps): update dependency polyfill to 9.24.1 by @​thomhurst in
thomhurst/TUnit#5365
* chore(deps): update dependency polyfill to 9.24.1 by @​thomhurst in
thomhurst/TUnit#5364


**Full Changelog**:
thomhurst/TUnit@v1.24.31...v1.25.0

## 1.24.31

<!-- Release notes generated using configuration in .github/release.yml
at v1.24.31 -->

## What's Changed
### Other Changes
* Fix Aspire 13.2.0+ timeout caused by ProjectRebuilderResource being
awaited by @​Copilot in thomhurst/TUnit#5335
* chore(deps): update dependency polyfill to 9.24.0 by @​thomhurst in
thomhurst/TUnit#5349
* Fix nullable IParsable type recognition in source generator and
analyzer by @​Copilot in thomhurst/TUnit#5354
* fix: resolve race condition in HookExecutionOrderTests by @​thomhurst
in thomhurst/TUnit#5355
* Fix MaxExternalSpansPerTest cap bypass when Activity.Parent chain is
broken by @​Copilot in thomhurst/TUnit#5352
### Dependencies
* chore(deps): update tunit to 1.24.18 by @​thomhurst in
thomhurst/TUnit#5340
* chore(deps): update dependency stackexchange.redis to 2.12.14 by
@​thomhurst in thomhurst/TUnit#5343
* chore(deps): update verify to 31.15.0 by @​thomhurst in
thomhurst/TUnit#5346
* chore(deps): update dependency polyfill to 9.24.0 by @​thomhurst in
thomhurst/TUnit#5348


**Full Changelog**:
thomhurst/TUnit@v1.24.18...v1.24.31

## 1.24.18

<!-- Release notes generated using configuration in .github/release.yml
at v1.24.18 -->

## What's Changed
### Other Changes
* feat(mocks): shorter, more readable generated mock type names by
@​thomhurst in thomhurst/TUnit#5334
* Fix DisposeAsync() ordering for nested property injection by @​Copilot
in thomhurst/TUnit#5337
### Dependencies
* chore(deps): update tunit to 1.24.13 by @​thomhurst in
thomhurst/TUnit#5331


**Full Changelog**:
thomhurst/TUnit@v1.24.13...v1.24.18

## 1.24.13

<!-- Release notes generated using configuration in .github/release.yml
at v1.24.13 -->

## What's Changed
### Other Changes
* perf(mocks): optimize MockEngine for lower allocation and faster
verification by @​thomhurst in
thomhurst/TUnit#5319
* Remove defunct `UseTestingPlatformProtocol` reference for vscode by
@​erwinkramer in thomhurst/TUnit#5328
* perf(aspnetcore): prevent thread pool starvation during parallel
WebApplicationTest server init by @​thomhurst in
thomhurst/TUnit#5329
* fix TUnit0073 for when type from from another assembly by @​SimonCropp
in thomhurst/TUnit#5322
* Fix implicit conversion operators bypassed in property injection casts
by @​Copilot in thomhurst/TUnit#5317
* fix(mocks): skip non-virtual 'new' methods when discovering mockable
members by @​thomhurst in thomhurst/TUnit#5330
* feat(mocks): IFoo.Mock() discovery with generic fallback and ORP
resolution by @​thomhurst in
thomhurst/TUnit#5327
### Dependencies
* chore(deps): update tunit to 1.24.0 by @​thomhurst in
thomhurst/TUnit#5315
* chore(deps): update aspire to 13.2.1 by @​thomhurst in
thomhurst/TUnit#5323
* chore(deps): update verify to 31.14.0 by @​thomhurst in
thomhurst/TUnit#5325

## New Contributors
* @​erwinkramer made their first contribution in
thomhurst/TUnit#5328

**Full Changelog**:
thomhurst/TUnit@v1.24.0...v1.24.13

## 1.24.0

<!-- Release notes generated using configuration in .github/release.yml
at v1.24.0 -->

## What's Changed
### Other Changes
* perf: optimize TUnit.Mocks hot paths by @​thomhurst in
thomhurst/TUnit#5304
* fix: resolve System.Memory version conflict on .NET Framework (net462)
by @​thomhurst in thomhurst/TUnit#5303
* fix: resolve CS0460/CS0122/CS0115 when mocking concrete classes from
external assemblies by @​thomhurst in
thomhurst/TUnit#5310
* feat(mocks): parameterless Returns() and ReturnsAsync() for async
methods by @​thomhurst in thomhurst/TUnit#5309
* Fix typo in NUnit manual migration guide by @​aa-ko in
thomhurst/TUnit#5312
* refactor(mocks): unify Mock.Of<T>() and Mock.OfPartial<T>() into
single API by @​thomhurst in
thomhurst/TUnit#5311
* refactor(mocks): clean up Mock API surface by @​thomhurst in
thomhurst/TUnit#5314
* refactor(mocks): remove generic/untyped overloads from public API by
@​thomhurst in thomhurst/TUnit#5313
### Dependencies
* chore(deps): update tunit to 1.23.7 by @​thomhurst in
thomhurst/TUnit#5305
* chore(deps): update dependency mockolate to 2.1.1 by @​thomhurst in
thomhurst/TUnit#5307

## New Contributors
* @​aa-ko made their first contribution in
thomhurst/TUnit#5312

**Full Changelog**:
thomhurst/TUnit@v1.23.7...v1.24.0

Commits viewable in [compare
view](thomhurst/TUnit@v1.23.7...v1.28.7).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=TUnit.Core&package-manager=nuget&previous-version=1.23.7&new-version=1.28.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Arg.IsNull<T> produces nullability warnings

1 participant