Skip to content

fix: resolve CS8920 when mocking interfaces whose members return static-abstract interfaces#5154

Merged
thomhurst merged 7 commits intothomhurst:mainfrom
lucaxchaves:fix/filter-static-abstract-in-mock-members-builder
Mar 17, 2026
Merged

fix: resolve CS8920 when mocking interfaces whose members return static-abstract interfaces#5154
thomhurst merged 7 commits intothomhurst:mainfrom
lucaxchaves:fix/filter-static-abstract-in-mock-members-builder

Conversation

@lucaxchaves
Copy link
Contributor

@lucaxchaves lucaxchaves commented Mar 13, 2026

Description

Continues the fix from #5070 for issue #5069 — CS8920 compiler errors when mocking AWS SDK interfaces (e.g. IAmazonDynamoDB) that inherit from IAmazonService, which declares:

static abstract IAmazonService CreateDefaultServiceClient(AWSCredentials awsCredentials, ClientConfig clientConfig);

Because IAmazonService itself has static abstract members, using it as a generic type argument triggers CS8920. The mock source generator was emitting MethodSetupBuilder<IAmazonService> and HandleCallWithReturn<IAmazonService>, causing every project that mocks such interfaces to fail to build.

Expected Behavior

Mocking an interface that contains methods returning an interface with static abstract members should compile without CS8920 errors. Setup and verification should work for those members via VoidMockMethodCall (the same pattern already used for ref struct return types).

Actual Behavior

error CS8920: The interface 'Amazon.Runtime.IAmazonService' cannot be used as type argument.
Static member 'IAmazonService.CreateDefaultServiceClient(...)' does not have a most specific implementation in the interface.

Steps to Reproduce

public interface IAmazonService
{
    static abstract IAmazonService CreateDefaultServiceClient(
        AWSCredentials awsCredentials, ClientConfig clientConfig);
}

public interface IAmazonDynamoDB : IAmazonService { /* ... */ }

[assembly: TUnit.Mocks.GenerateMock(typeof(IAmazonDynamoDB))]
// → build fails with CS8920

Root Cause & Fix

The generator tracked IsStaticAbstract on members but had no concept of whether a member's return type is itself an interface with static abstract members. All three builders emitted the return type directly as a generic type argument.

Added IsReturnTypeStaticAbstractInterface to MockMemberModel, populated during discovery. All three builders now fall back to the object?-cast pattern when this flag is set:

  • MockMembersBuilder — emits VoidMockMethodCall instead of MockMethodCall<T>
  • MockBridgeBuilder — uses HandleCallWithReturn<object?> + cast in DIM implementations
  • MockImplBuilder — uses HandleCallWithReturn<object?> + cast across interface, wrap, and partial mock paths (sync and async)

Testing

  • StaticAbstractMemberTests expanded with the real AWS SDK interface shape, including static abstract IAmazonService CreateDefaultServiceClient(...) — the CS8920 transitive scenario
  • Snapshot test Interface_With_Static_Abstract_Transitive_Return_Type updated
  • All 15 snapshot tests pass; no regression in existing static abstract member tests

Checklist

  • I've searched existing issues to ensure this isn't a duplicate
  • Fix applies to interface mocks, wrap mocks, and partial mocks
  • Both sync and async return type paths handled
  • Snapshot .verified.txt committed; no .received.txt committed
  • No regression in existing static abstract member tests
  • I've confirmed this issue occurs when running via dotnet test, not just in my IDE

Lucas Chaves and others added 3 commits March 13, 2026 15:22
…ic-abstract interfaces

When mocking AWS SDK interfaces (e.g. IAmazonDynamoDB) that inherit from IAmazonService,
the source generator emitted MethodSetupBuilder<IAmazonService> and
HandleCallWithReturn<IAmazonService>. Since IAmazonService declares
'static abstract IAmazonService CreateDefaultServiceClient(...)', using it as a
generic type argument triggers CS8920.

Add IsReturnTypeStaticAbstractInterface to MockMemberModel, populated during
discovery when the (unwrapped) return type is an interface with static abstract
members. All three builders fall back to the object?-cast pattern (analogous to
the existing IsRefStructReturn handling):

- MockMembersBuilder: emits VoidMockMethodCall instead of MockMethodCall<T>
- MockBridgeBuilder: uses HandleCallWithReturn<object?> + cast in DIM implementations
- MockImplBuilder: uses HandleCallWithReturn<object?> + cast in all mock impl paths

Also expand StaticAbstractMemberTests with the AWS SDK interface shape:
IClientConfig property, static abstract CreateDefaultClientConfig() (concrete
return type, fully typed setup), and static abstract CreateDefaultServiceClient()
(returns IAmazonService — the CS8920 transitive scenario, verified via
VoidMockMethodCall).
…property

- Add braces to all bare if/else blocks in MockBridgeBuilder, MockImplBuilder,
  and MemberDiscovery (SA1503 / SonarAnalyzer S121)
- Use unwrappedArg/unwrappedDefault variables in the async HandleCallWithReturn
  format strings in MockImplBuilder (removes unused-variable warnings)
- Rename AWSCredentials.SecretKey → AuthSignature to resolve S2068
  (hardcoded-credentials false positive on property name)
Copy link
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-structured fix that correctly follows the existing IsRefStructReturn pattern to handle CS8920. The discovery logic, model updates, and all three builders are consistently updated. Good comprehensive test coverage. A few things worth flagging:


Primary concern: VoidMockMethodCall for non-void methods silently drops .Returns() capability

The biggest issue is a user-experience regression: methods that return an interface with static abstract members are treated as void for the setup API. Since VoidMockMethodCall has no .Returns() method, users cannot configure a return value:

var mock = Mock.Of<TUnit_Mocks_Tests_IAmazonService_Mockable>();

// This compiles, but silently ignores any return value setup — VoidMockMethodCall has no .Returns()
mock.CreateDefaultServiceClient(Arg.Any<AWSCredentials>(), Arg.Any<ClientConfig>())
    .Throws(new InvalidOperationException("unavailable")); // ✅ works
    
// There is no way to write:
//   mock.CreateDefaultServiceClient(...).Returns(someService); // ❌ not possible

The existing test suite confirms this — Static_Abstract_CreateDefaultServiceClient_Returns_Null_By_Default has no setup of a return value, and there's no positive test showing return value configuration.

This is a semantic mismatch: the method IS non-void (it returns IAmazonService), but we're treating it as void at the API level. The underlying engine already stores values as object? (as demonstrated by the HandleCallWithReturn<object?> cast), so a typed wrapper is feasible.

Suggested approach: Introduce a new ObjectReturnMockMethodCall (or similar) type that stores the return value as object? but exposes a typed Returns(object? value):

public sealed class ObjectReturnMockMethodCall : IObjectReturnMethodSetup, ICallVerification
{
    // Identical to MockMethodCall<TReturn> but with Returns(object? value)
    // so users can still configure return values
}

Then the generator emits ObjectReturnMockMethodCall instead of VoidMockMethodCall for SAI-returning methods. This preserves the .Returns() / .WasCalled() contract users expect.

If introducing a new type is out of scope for this PR, the limitation should at least be documented in the XML doc on IsReturnTypeStaticAbstractInterface and in comments on the generated setup method.


Minor: Redundant intermediate variable in non-SAI async path

In GenerateWrapMethodBody and GeneratePartialMethodBody, the non-SAI branch introduces an unnecessary rename:

// After the PR, non-SAI async path emits:
var __result = __rawResult;   // ← just a rename

This comes from the dual-branch structure:

if (method.IsReturnTypeStaticAbstractInterface)
    writer.AppendLine($"var __result = ({method.UnwrappedReturnType})__rawResult!;");
else
    writer.AppendLine($"var __result = __rawResult;");  // ← could just use __rawResult directly below

The else branch is harmless (compiler optimises it away) but slightly noisy in the generated code.


Minor: IsInterfaceWithStaticAbstractMembers — two loops can be unified

The helper currently iterates direct members first, then AllInterfaces members. Since AllInterfaces in Roslyn does NOT include the type itself (only inherited interfaces), the logic is correct, but a combined LINQ expression would be slightly cleaner and less error-prone:

private static bool IsInterfaceWithStaticAbstractMembers(ITypeSymbol type)
{
    if (type is not INamedTypeSymbol { TypeKind: TypeKind.Interface } namedType)
        return false;

    return namedType.GetMembers().Concat(namedType.AllInterfaces.SelectMany(i => i.GetMembers()))
        .Any(m => m.IsStatic && m.IsAbstract);
}

This is stylistic — the existing two-loop form is perfectly correct.


What's done well

  • Consistently applies the fix across all three builders (MockImplBuilder, MockBridgeBuilder, MockMembersBuilder) and both sync and async code paths.
  • IsInterfaceWithStaticAbstractMembers correctly uses AllInterfaces (transitive) to catch the exact AWS SDK pattern where the method return type inherits the static abstract member rather than defining it directly.
  • Using GetAsyncInnerTypeSymbol() ?? returnType to handle Task<ISai> / ValueTask<ISai> is correct.
  • Snapshot tests updated and committed, no .received.txt left in the tree.
  • The null! → cast pattern ((T)engine.HandleCallWithReturn<object?>(...)!) is safe for reference-type interfaces and consistent with the ref struct fallback.

Summary: The CS8920 fix is solid. The main concern worth addressing before merge is that users lose the ability to configure return values for SAI-returning methods when using VoidMockMethodCall — this is a non-obvious capability regression that could be avoided with a new untyped return call type (or at minimum should be documented).

@thomhurst
Copy link
Owner

Thanks! 😄 Claude has identified some potential bugs

Lucas Chaves and others added 2 commits March 15, 2026 12:19
…e .Returns()

Methods returning interfaces with static abstract members (CS8920) were
using VoidMockMethodCall, which silently dropped .Returns() capability.
Switch to MockMethodCall<object?> so users can configure return values
via the object? → T cast path the engine already uses.

Also fix redundant var __result = __rawResult in async non-SAI paths,
unify IsInterfaceWithStaticAbstractMembers into single LINQ expression,
add curly braces to all braceless if blocks, and add a test proving
.Returns() works for SAI-returning methods.
@lucaxchaves
Copy link
Contributor Author

@thomhurst done!

Copy link
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 follow-up to my previous review. Let me first check which concerns have been addressed, then flag any remaining issues.


Previous concerns — status

VoidMockMethodCall drops .Returns() capability ✅ Fixed

The previous review noted that SAI-returning methods were treated as void at the setup API, silently dropping .Returns(). This has been correctly addressed:

  • GenerateUnifiedSealedClass now calls GenerateReturnUnifiedClass(writer, ..., "object?", ...) instead of GenerateVoidUnifiedClass, so the generated class exposes .Returns().
  • The extension method builder now emits MockMethodCall<object?> instead of VoidMockMethodCall.
  • New test Static_Abstract_CreateDefaultServiceClient_Returns_Configured_Value confirms that .Returns() works end-to-end.

The snapshot also confirms: the extension method now returns MockMethodCall<object?> and the impl body casts back to IConfigProvider.


Remaining concerns

1. Type-safety loss at the setup API is undocumented

The setup extension method now returns MockMethodCall<object?> instead of MockMethodCall<IConfigProvider>. This means:

// Compiles fine, but crashes at the call site with InvalidCastException at runtime
mock.GetConfigProvider().Returns(new NotAConfigProvider());  // ← object? accepts anything

The trade-off is unavoidable given CS8920, but it should be called out in the generated XML doc comment (or at minimum in the IsReturnTypeStaticAbstractInterface doc comment already added to the model). Users need to know they've lost compile-time type safety for the return value. Suggestion:

/// <returns>
/// A <see cref="MockMethodCall{T}"/> typed as <c>object?</c> because the return type
/// (<typeparamref name="..."/>) contains static abstract members and cannot be used as
/// a generic type argument (CS8920). Pass a value that implements the return interface
/// to <c>.Returns()</c> — incorrect types will cause <see cref="InvalidCastException"/> at call time.
/// </returns>

2. Unrelated WaitsForAssertionTests.cs changes should be a separate PR

This PR significantly weakens the performance test assertions in WaitsFor_Performance_Many_Quick_Polls:

  • Timeout: 5s → 30s
  • Target count: IsGreaterThan(20)IsGreaterThan(5)
  • Assertion: IsGreaterThanOrEqualTo(21)IsGreaterThanOrEqualTo(6)
  • Upper bound: IsLessThan(TimeSpan.FromSeconds(5))IsLessThan(TimeSpan.FromSeconds(30))

And in WaitsFor_With_Custom_Polling_Interval: timeout 1s → 30s.

These are unrelated to CS8920 mocking fixes and make the tests nearly trivially easy to pass. If these are addressing legitimate CI flakiness, they deserve their own PR with justification (and ideally a proper fix to the flakiness root cause rather than 30x-larger timeouts and 4x-fewer assertions).


What's well done

  • All three builders consistently updated across both sync and async paths, wrap/partial/impl.
  • IsInterfaceWithStaticAbstractMembers now correctly handles the transitive case: a return type interface that inherits a static abstract member (the exact AWS SDK pattern) is detected via AllInterfaces.SelectMany(i => i.GetMembers()).
  • Tests are comprehensive: null default, configured return value, verification, exception throwing — all four scenarios are covered.
  • Snapshot is committed without .received.txt files.
  • The null! → cast pattern (TReturn)engine.HandleCallWithReturn<object?>(...)! is safe for reference-type interfaces (null cast succeeds; null default is consistent with other unmocked methods).

Summary: The CS8920 fix is solid and the primary concern from the previous review (lost .Returns() capability) has been resolved. Two things worth addressing before merge: (1) document the type-safety trade-off in the generated setup API, and (2) move the unrelated WaitsForAssertionTests.cs weakening into a separate, justified PR.

…assertions

Document the object? type erasure on generated setup methods for
static-abstract-interface returns (CS8920) and restore stricter
timeout/assertion values in WaitsForAssertionTests.
Copy link
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 — Follow-up (Round 3)

This is a follow-up to the previous two reviews. All outstanding concerns have now been resolved.


Previous concerns — final status

VoidMockMethodCall drops .Returns() capability ✅ Fixed (Round 2)
Resolved by switching to MockMethodCall<object?> via GenerateReturnUnifiedClass.

Type-safety loss at the setup API is undocumented ✅ Fixed (Round 3)
MockMembersBuilder now emits XML doc comments on the generated extension methods when IsReturnTypeStaticAbstractInterface is set, explaining that the return type is object? due to CS8920 and that incorrect types will cause InvalidCastException at call time (line ~603 in the current builder).

Unrelated WaitsForAssertionTests.cs weakening ✅ Fixed (Round 3)
The final commit restores the stricter assertion values (IsGreaterThan(20), 5 s timeout) that had been loosened to 30 s / 5 polls in a previous commit. The test file is back to its original intent.


Overall assessment

The fix is correct, comprehensive, and well-structured:

  • IsReturnTypeStaticAbstractInterface is detected transitively via AllInterfaces.SelectMany(...), which is exactly what is needed for the AWS SDK pattern where the return type inherits the static abstract member rather than declaring it directly.
  • All three builders (MockImplBuilder, MockBridgeBuilder, MockMembersBuilder) are updated consistently across both sync and async code paths, as well as interface, wrap, and partial mock modes.
  • The object? → cast pattern (T)engine.HandleCallWithReturn<object?>(...)! is safe for reference-type interfaces and is consistent with the existing IsRefStructReturn fallback.
  • Snapshot tests are committed (.verified.txt), no .received.txt files remain.
  • The generated XML doc comments adequately communicate the type-safety trade-off to users consuming the setup API.

The PR is ready to merge.

@thomhurst
Copy link
Owner

Thanks @lucaxchaves - looks ready to go - just a failing test

@thomhurst
Copy link
Owner

Ty!

@thomhurst thomhurst merged commit f5fccea into thomhurst:main Mar 17, 2026
9 of 11 checks passed
@lucaxchaves lucaxchaves deleted the fix/filter-static-abstract-in-mock-members-builder branch March 17, 2026 20:39
@claude claude bot mentioned this pull request Mar 17, 2026
1 task
This was referenced Mar 17, 2026
PhilippNaused pushed a commit to PhilippNaused/Bshox that referenced this pull request Mar 18, 2026
Updated [TUnit.Core](https://github.com/thomhurst/TUnit) from 1.19.0 to
1.19.74.

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

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

## 1.19.74

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

## What's Changed
### Other Changes
* feat: per-hook activity spans with method names by @​thomhurst in
thomhurst/TUnit#5159
* fix: add tooltip to truncated span names in HTML report by @​thomhurst
in thomhurst/TUnit#5164
* Use enum names instead of numeric values in test display names by
@​Copilot in thomhurst/TUnit#5178
* fix: resolve CS8920 when mocking interfaces whose members return
static-abstract interfaces by @​lucaxchaves in
thomhurst/TUnit#5154
### Dependencies
* chore(deps): update tunit to 1.19.57 by @​thomhurst in
thomhurst/TUnit#5157
* chore(deps): update dependency gitversion.msbuild to 6.6.1 by
@​thomhurst in thomhurst/TUnit#5160
* chore(deps): update dependency gitversion.tool to v6.6.1 by
@​thomhurst in thomhurst/TUnit#5161
* chore(deps): update dependency polyfill to 9.20.0 by @​thomhurst in
thomhurst/TUnit#5163
* chore(deps): update dependency polyfill to 9.20.0 by @​thomhurst in
thomhurst/TUnit#5162
* chore(deps): update dependency polyfill to 9.21.0 by @​thomhurst in
thomhurst/TUnit#5166
* chore(deps): update dependency polyfill to 9.21.0 by @​thomhurst in
thomhurst/TUnit#5167
* chore(deps): update dependency polyfill to 9.22.0 by @​thomhurst in
thomhurst/TUnit#5168
* chore(deps): update dependency polyfill to 9.22.0 by @​thomhurst in
thomhurst/TUnit#5169
* chore(deps): update dependency coverlet.collector to 8.0.1 by
@​thomhurst in thomhurst/TUnit#5177

## New Contributors
* @​lucaxchaves made their first contribution in
thomhurst/TUnit#5154

**Full Changelog**:
thomhurst/TUnit@v1.19.57...v1.19.74

## 1.19.57

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

## What's Changed
### Other Changes
* fix: use unique artifact names to avoid collisions in matrix builds by
@​thomhurst in thomhurst/TUnit#5132
* fix: resolve IndexOutOfRangeException with MethodDataSource<T> on
class (#​5118) by @​thomhurst in
thomhurst/TUnit#5137
* fix: prevent StringEqualsAssertion from matching non-string types by
@​thomhurst in thomhurst/TUnit#5156
### Dependencies
* chore(deps): update tunit to 1.19.22 by @​thomhurst in
thomhurst/TUnit#5117
* chore(deps): update dependency fsharp.core to 10.0.104 by @​thomhurst
in thomhurst/TUnit#5119
* chore(deps): update dependency microsoft.entityframeworkcore to 10.0.4
by @​thomhurst in thomhurst/TUnit#5120
* chore(deps): update dependency fsharp.core to v11 by @​thomhurst in
thomhurst/TUnit#5128
* chore(deps): update dependency microsoft.templateengine.authoring.cli
to v10.0.200 by @​thomhurst in
thomhurst/TUnit#5122
* chore(deps): update dependency dotnet-sdk to v10.0.200 by @​thomhurst
in thomhurst/TUnit#5123
* chore(deps): update dependency microsoft.sourcelink.github to 10.0.200
by @​thomhurst in thomhurst/TUnit#5121
* chore(deps): update dependency system.commandline to 2.0.4 by
@​thomhurst in thomhurst/TUnit#5125
* chore(deps): update microsoft.extensions to 10.0.4 by @​thomhurst in
thomhurst/TUnit#5127
* chore(deps): update microsoft.build to 18.4.0 by @​thomhurst in
thomhurst/TUnit#5129
* chore(deps): update microsoft.aspnetcore to 10.0.4 by @​thomhurst in
thomhurst/TUnit#5126
* chore(deps): update dependency
microsoft.templateengine.authoring.templateverifier to 10.0.200 by
@​thomhurst in thomhurst/TUnit#5124
* chore(deps): update microsoft.extensions to 10.4.0 by @​thomhurst in
thomhurst/TUnit#5130
* chore(deps): update dependency
opentelemetry.instrumentation.aspnetcore to 1.15.1 by @​thomhurst in
thomhurst/TUnit#5136
* chore(deps): update dependency vogen to 8.0.5 by @​thomhurst in
thomhurst/TUnit#5133
* chore(deps): update dependency npgsql to 10.0.2 by @​thomhurst in
thomhurst/TUnit#5139
* chore(deps): update dependency microsoft.sourcelink.github to 10.0.201
by @​thomhurst in thomhurst/TUnit#5141
* chore(deps): update dependency microsoft.entityframeworkcore to 10.0.5
by @​thomhurst in thomhurst/TUnit#5140
* chore(deps): update dependency microsoft.templateengine.authoring.cli
to v10.0.201 by @​thomhurst in
thomhurst/TUnit#5142
* chore(deps): update dependency
microsoft.templateengine.authoring.templateverifier to 10.0.201 by
@​thomhurst in thomhurst/TUnit#5143
* chore(deps): update dependency npgsql.entityframeworkcore.postgresql
to 10.0.1 by @​thomhurst in thomhurst/TUnit#5145
* chore(deps): update dependency dotnet-sdk to v10.0.201 by @​thomhurst
in thomhurst/TUnit#5144
* chore(deps): update dependency system.commandline to 2.0.5 by
@​thomhurst in thomhurst/TUnit#5146
* chore(deps): update microsoft.aspnetcore to 10.0.5 by @​thomhurst in
thomhurst/TUnit#5147
* chore(deps): update dependency testcontainers.kafka to 4.11.0 by
@​thomhurst in thomhurst/TUnit#5149
* chore(deps): update microsoft.extensions to 10.0.5 by @​thomhurst in
thomhurst/TUnit#5148
* chore(deps): update dependency testcontainers.postgresql to 4.11.0 by
@​thomhurst in thomhurst/TUnit#5150
* chore(deps): update dependency testcontainers.redis to 4.11.0 by
@​thomhurst in thomhurst/TUnit#5151
* chore(deps): update dependency stackexchange.redis to 2.12.1 by
@​thomhurst in thomhurst/TUnit#5153


**Full Changelog**:
thomhurst/TUnit@v1.19.22...v1.19.57

## 1.19.22

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

## What's Changed
### Other Changes
* Remove redundant prefixes from tracing timeline spans by @​thomhurst
in thomhurst/TUnit#5111
* Render span tags and events on separate lines by @​thomhurst in
thomhurst/TUnit#5113
* Demote granular internal logs from Debug to Trace level by @​thomhurst
in thomhurst/TUnit#5116
### Dependencies
* chore(deps): update tunit to 1.19.16 by @​thomhurst in
thomhurst/TUnit#5109


**Full Changelog**:
thomhurst/TUnit@v1.19.16...v1.19.22

## 1.19.16

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

## What's Changed
### Other Changes
* Truncate exceptions in GitHub summary tables by @​thomhurst in
thomhurst/TUnit#5108
### Dependencies
* chore(deps): update tunit to 1.19.11 by @​thomhurst in
thomhurst/TUnit#5106
* chore(deps): bump dompurify from 3.3.0 to 3.3.2 in /docs by
@​dependabot[bot] in thomhurst/TUnit#5096
* chore(deps): bump svgo from 3.2.0 to 3.3.3 in /docs by
@​dependabot[bot] in thomhurst/TUnit#5086


**Full Changelog**:
thomhurst/TUnit@v1.19.11...v1.19.16

## 1.19.11

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

## What's Changed
### Other Changes
* Fix HTML report sort to also reorder groups by @​thomhurst in
thomhurst/TUnit#5103
* fix: correct expand-all icon SVG in HTML report by @​slang25 in
thomhurst/TUnit#5105
* Avoid some redundant list allocations by @​SimonCropp in
thomhurst/TUnit#4963
* avoid some redundant enumerable alloc by @​SimonCropp in
thomhurst/TUnit#4972
* use char instead of string for joins by @​SimonCropp in
thomhurst/TUnit#4989
### Dependencies
* chore(deps): update dependency nunit to 4.5.1 by @​thomhurst in
thomhurst/TUnit#5097
* chore(deps): update tunit to 1.19.0 by @​thomhurst in
thomhurst/TUnit#5099
* chore(deps): update dependency humanizer to 3.0.10 by @​thomhurst in
thomhurst/TUnit#5101
* chore(deps): update dependency nunit.analyzers to 4.12.0 by
@​thomhurst in thomhurst/TUnit#5102


**Full Changelog**:
thomhurst/TUnit@v1.19.0...v1.19.11

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

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=TUnit.Core&package-manager=nuget&previous-version=1.19.0&new-version=1.19.74)](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 <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</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.

2 participants