Skip to content

Add mock library benchmarks: TUnit.Mocks vs Moq, NSubstitute, FakeItEasy#5284

Merged
thomhurst merged 4 commits intomainfrom
copilot/add-benchmarks-for-mocking-libraries
Mar 28, 2026
Merged

Add mock library benchmarks: TUnit.Mocks vs Moq, NSubstitute, FakeItEasy#5284
thomhurst merged 4 commits intomainfrom
copilot/add-benchmarks-for-mocking-libraries

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 28, 2026

Adds BenchmarkDotNet benchmarks comparing TUnit.Mocks (source-generated) against Moq, NSubstitute, and FakeItEasy (runtime proxy), with CI automation and docs integration.

Benchmark project (TUnit.Mocks.Benchmarks)

Six benchmark classes covering common mocking operations:

  • MockCreationBenchmarks — instance creation for simple and complex interfaces
  • SetupBenchmarks — return values, argument matchers, multiple setups
  • InvocationBenchmarks — single calls, string returns, 100-call loops
  • VerificationBenchmarks — exact count, never-called, multi-method verification
  • CallbackBenchmarks — simple callbacks and argument capture
  • CombinedWorkflowBenchmarks — full create → setup → invoke → verify workflow
[Benchmark(Description = "TUnit.Mocks")]
public void TUnitMocks_FullWorkflow()
{
    var repoMock = Mock.Of<IUserRepository>();
    repoMock.GetById(1).Returns(new User { Id = 1, Name = "Alice" });
    var user = repoMock.Object.GetById(1);
    repoMock.GetById(1).WasCalled(Times.Once);
}

Uses TUnitArg/NSubArg global aliases to disambiguate TUnit.Mocks.Arguments.Arg from NSubstitute.Arg.

CI workflow (.github/workflows/mock-benchmarks.yml)

  • Daily schedule (2am UTC) + workflow_dispatch
  • Matrix strategy: each benchmark class runs in parallel
  • Results processed via .github/scripts/process-mock-benchmarks.js → generates markdown pages with Mermaid charts + JSON data
  • Auto-creates and merges PR with updated docs on main

Follows the same pattern as the existing speed-comparison.yml workflow.

Documentation

  • Placeholder pages in docs/docs/benchmarks/mocks/ (auto-discovered by existing autogenerated sidebar config)
  • Static JSON in docs/static/benchmarks/mocks/ — populated automatically after first workflow run

Dependencies

  • Added Moq 4.20.72 and FakeItEasy 9.0.1 to Directory.Packages.props (NSubstitute 5.3.0 already present)
  • All three checked against GitHub Advisory DB — no vulnerabilities

⚡ Quickly spin up Copilot coding agent tasks from anywhere on your macOS or Windows machine with Raycast.

Copilot AI linked an issue Mar 28, 2026 that may be closed by this pull request
Copilot AI and others added 2 commits March 28, 2026 13:03
…mparing TUnit.Mocks against Moq, NSubstitute, and FakeItEasy

Agent-Logs-Url: https://github.com/thomhurst/TUnit/sessions/dc41f1a0-84fc-4e59-9172-30c841e9b52b

Co-authored-by: thomhurst <30480171+thomhurst@users.noreply.github.com>
…ock benchmarks

Agent-Logs-Url: https://github.com/thomhurst/TUnit/sessions/dc41f1a0-84fc-4e59-9172-30c841e9b52b

Co-authored-by: thomhurst <30480171+thomhurst@users.noreply.github.com>
Comment on lines +10 to +42
environment: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Pull Requests' }}
strategy:
matrix:
benchmark: [MockCreationBenchmarks, SetupBenchmarks, InvocationBenchmarks, VerificationBenchmarks, CallbackBenchmarks, CombinedWorkflowBenchmarks]
fail-fast: false
runs-on: ubuntu-latest
concurrency:
group: "mock-benchmarks-${{ matrix.benchmark }}"
cancel-in-progress: true

steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: 10.0.x

- name: Run Benchmark
run: dotnet run -c Release -- --filter "*${{ matrix.benchmark }}*" --exporters json github
working-directory: "TUnit.Mocks.Benchmarks"

- name: Upload Results
uses: actions/upload-artifact@v7
if: always()
with:
name: mock_benchmark_${{ matrix.benchmark }}
path: |
**/BenchmarkDotNet.Artifacts/**

process-and-upload-mock-benchmarks:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 2 days ago

In general, fix this by explicitly specifying minimal permissions for the affected job or at the workflow root. For this workflow, the job flagged by CodeQL is run-mock-benchmarks. It only needs to read the repository contents and upload artifacts; it does not create or modify any repository data (no pushes, issues, or PRs). Therefore the safest, non-breaking change is to add permissions: contents: read to that job. The second job, process-and-upload-mock-benchmarks, already has a permissions block and does not need changes.

Concretely:

  • Edit .github/workflows/mock-benchmarks.yml.
  • Under run-mock-benchmarks: (around line 9), add a permissions: block with contents: read, aligned with the job keys.
  • Leave process-and-upload-mock-benchmarks as-is.

No additional methods, imports, or dependencies are required; this is purely a YAML configuration change.

Suggested changeset 1
.github/workflows/mock-benchmarks.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/mock-benchmarks.yml b/.github/workflows/mock-benchmarks.yml
--- a/.github/workflows/mock-benchmarks.yml
+++ b/.github/workflows/mock-benchmarks.yml
@@ -7,6 +7,8 @@
 
 jobs:
   run-mock-benchmarks:
+    permissions:
+      contents: read
     environment: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Pull Requests' }}
     strategy:
       matrix:
EOF
@@ -7,6 +7,8 @@

jobs:
run-mock-benchmarks:
permissions:
contents: read
environment: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Pull Requests' }}
strategy:
matrix:
Copilot is powered by AI and may make mistakes. Always verify output.
Agent-Logs-Url: https://github.com/thomhurst/TUnit/sessions/dc41f1a0-84fc-4e59-9172-30c841e9b52b

Co-authored-by: thomhurst <30480171+thomhurst@users.noreply.github.com>
Copilot AI changed the title [WIP] Add benchmarks for TUnit.Mocks against popular mocking libraries Add mock library benchmarks: TUnit.Mocks vs Moq, NSubstitute, FakeItEasy Mar 28, 2026
Copilot AI requested a review from thomhurst March 28, 2026 13:19
Copilot AI temporarily deployed to Pull Requests March 28, 2026 16:09 Inactive
Copilot AI temporarily deployed to Pull Requests March 28, 2026 16:09 Inactive
@thomhurst thomhurst marked this pull request as ready for review March 28, 2026 16:09
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: Add mock library benchmarks (TUnit.Mocks vs Moq, NSubstitute, FakeItEasy)

This PR adds BenchmarkDotNet comparison benchmarks and a CI workflow for TUnit.Mocks. The overall structure is sensible and follows existing patterns in the repo (cf. speed-comparison.yml). Below are the issues I found, from most to least critical.


Critical / Correctness Issues

1. Unfair benchmark comparisons in VerificationBenchmarks and CallbackBenchmarks

Several TUnit.Mocks benchmarks do not correctly replicate what the competing libraries do.

In VerificationBenchmarks.TUnitMocks_VerifyNever, no mock object is ever invoked before asserting "never called" — which is correct — but in Moq_VerifyNever the equivalent is written without a .Setup() call first. Moq will still verify on an un-setup method (it tracks all calls implicitly), so the behaviour matches. However the asymmetry is fragile and will confuse readers who try to understand why the Moq version is faster/slower.

More seriously, in CallbackBenchmarks.TUnitMocks_CallbackWithArgs the callback captures a constant string "logged" rather than actually capturing the argument:

// TUnit.Mocks — captures a constant, does NOT read arguments
mock.Log(TUnitArg.Any<string>(), TUnitArg.Any<string>())
    .Callback(() => lastMessage = "logged");   // <-- argument not used

// Moq — correctly captures the second argument
mock.Setup(x => x.Log(It.IsAny<string>(), It.IsAny<string>()))
    .Callback<string, string>((level, msg) => lastMessage = msg);

This means the TUnit.Mocks "with args" benchmark does less work than its competitors, making it appear faster. This directly undermines the credibility of the benchmark. Either TUnit.Mocks needs a way to receive typed callback arguments (and the benchmark should use it), or the benchmark should be labelled differently and not compared against "with args" variants.

2. Auto-merge of CI-generated PRs using --admin

gh pr merge ${{ steps.create_pr.outputs.pull-request-number }} --squash --delete-branch --admin

Using --admin bypasses required status checks and branch protection rules. If a benchmark run produces corrupt or manipulated data (e.g. via a supply-chain attack on a dependency), it will be merged to main without review. The existing speed-comparison.yml does not use --admin. Either remove the flag and let the normal merge queue handle it, or add a required manual approval step before merging.

3. actions/checkout@v6 and actions/download-artifact@v8 — non-existent versions

At time of writing the latest released versions are actions/checkout@v4, actions/upload-artifact@v4, actions/download-artifact@v4, actions/setup-dotnet@v4, actions/setup-node@v4. The workflow references @v6, @v7, and @v8 which do not exist. The workflow will fail on its first run. The existing speed-comparison.yml correctly uses @v6/@v7/@v8 — please verify whether these are internal forks or mirrors before using them; if they are, a comment explaining this would help maintainers.


Design / Maintainability Issues

4. Hardcoded per-category artifact upload steps (DRY violation)

The process-and-upload-mock-benchmarks job has six identical "Upload X Benchmark" steps that differ only in the category name. When a new benchmark class is added, six places need to be updated (the matrix, the JS categoryMap, the upload steps, the PR body, and the placeholder docs). A single upload step with a glob pattern (docs/docs/benchmarks/mocks/** / docs/static/benchmarks/mocks/**) would make the workflow self-extending:

- name: Upload All Benchmark Artifacts
  uses: actions/upload-artifact@v4
  if: always()
  with:
    name: mock-benchmark-all
    path: |
      docs/docs/benchmarks/mocks/
      docs/static/benchmarks/mocks/
    retention-days: 90

5. Mermaid xychart-beta chart mixes all libraries in a single bar series

In process-mock-benchmarks.js the generated Mermaid chart uses one bar array containing measurements for all four libraries side-by-side without labelling which bar belongs to which library:

bar [${data.map(d => parseMeanValue(d.Mean)).join(', ')}]

xychart-beta does not support a legend when only a single bar series is declared this way. Readers cannot tell which bar is TUnit.Mocks vs Moq. Consider using separate bar entries named per-library, or switching to a pie or table-only presentation until Mermaid's xychart supports grouped bars properly.

6. parseMeanValue silently returns 0 for unrecognised input

function parseMeanValue(meanStr) {
  if (!meanStr) return 0;
  const cleaned = meanStr.replace(/,/g, '');
  const match = cleaned.match(/[\d.]+/);
  return match ? parseFloat(match[0]) : 0;
}

A return value of 0 is indistinguishable from a genuine zero measurement and will silently corrupt chart data. The function should throw (or at minimum console.warn) when it cannot parse a value, so a broken BenchmarkDotNet output format doesn't produce a misleading chart.

7. Unit normalisation is incomplete

getUnit checks for μs/us but BenchmarkDotNet can also output ns, ms, s, and mixed-unit tables where individual rows use different units. The chart renders all values on the same y-axis using a single unit derived from the first row (data[0]?.Mean), which will produce wildly incorrect charts if rows use different units (e.g. TUnit.Mocks in ns vs Moq in μs).

8. BenchmarkDotNet package version is unpinned

Directory.Packages.props already contains a BenchmarkDotNet entry (used by the existing speed-comparison benchmarks). The new .csproj references BenchmarkDotNet and BenchmarkDotNet.Annotations without version overrides, so they inherit the central version — this is correct, but it should be verified that the central version is recent enough to support [SimpleJob] and the JSON/GitHub exporters used here.

9. TUnit.Mocks.Generated global using may not be portable

global using TUnit.Mocks.Generated;

This namespace is emitted by the source generator for each consuming project. If the source generator is not running (e.g. a build that skips analyzers, or a CI step that only restores without building), the project will fail to compile rather than giving a clear error. A comment explaining the dependency would help.

10. Missing [Baseline] attribute

BenchmarkDotNet supports marking one benchmark as the baseline with [Benchmark(Baseline = true)], which produces a "Ratio" column showing relative performance. Since the point of these benchmarks is to show TUnit.Mocks is faster, adding Baseline = true to the TUnit.Mocks methods would make the results immediately readable without needing the Mermaid chart.


Minor / Nits

  • The process-mock-benchmarks.js script contains duplicate console.log('... Processing mock benchmark results...') calls (lines 14 and 124) — one should be removed.
  • Placeholder JSON files committed to docs/static/benchmarks/mocks/ (latest.json, summary.json) use the string "placeholder" for timestamps; these will appear verbatim in the docs until the first CI run. Consider using an ISO timestamp or omitting the files and having the script create them on first run.
  • The CI workflow only runs when github.ref == 'refs/heads/main' for the post-processing job, but the schedule trigger always fires regardless of branch context. This means a scheduled run on a non-main branch will run all six benchmarks and then skip the post-processing silently — this is likely intentional but worth a comment.
  • new List<User>() in SetupBenchmarks should use [] (collection expression) per the project's "modern C#" guideline.

Summary

The most important issues to address before merging are (1) the unfair callback-with-args benchmark, (2) the --admin auto-merge, and (3) verifying the action versions. The DRY violation and chart correctness issues (4–5) are also worth fixing before this becomes a long-lived daily workflow.

This was referenced Mar 30, 2026
intellitect-bot pushed a commit to IntelliTect/EssentialCSharp.Web that referenced this pull request Mar 30, 2026
Updated [TUnit](https://github.com/thomhurst/TUnit) from 1.21.30 to
1.23.7.

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

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

## 1.23.7

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

## What's Changed
### Other Changes
* feat: use results directory provided by Microsoft Testing Platform in
HtmlReporter by @​DavidZidar in
thomhurst/TUnit#5294
* feat: add benchmarks for Imposter and Mockolate mocking frameworks by
@​vbreuss in thomhurst/TUnit#5295
* feat: add TUnit0080 analyzer for missing polyfill types by @​thomhurst
in thomhurst/TUnit#5292
* fix: respect user-set TUnitImplicitUsings from Directory.Build.props
by @​thomhurst in thomhurst/TUnit#5280
* perf: optimize TUnit.Mocks hot paths by @​thomhurst in
thomhurst/TUnit#5300
### Dependencies
* chore(deps): update tunit to 1.22.19 by @​thomhurst in
thomhurst/TUnit#5296

## New Contributors
* @​DavidZidar made their first contribution in
thomhurst/TUnit#5294

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

## 1.22.19

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

## What's Changed
### Other Changes
* Add mock library benchmarks: TUnit.Mocks vs Moq, NSubstitute,
FakeItEasy by @​Copilot in thomhurst/TUnit#5284
* perf: lazily initialize optional MockEngine collections by @​thomhurst
in thomhurst/TUnit#5289
* Always emit TUnit.Mocks.Generated namespace from source generator by
@​Copilot in thomhurst/TUnit#5282
### Dependencies
* chore(deps): update tunit to 1.22.6 by @​thomhurst in
thomhurst/TUnit#5285


**Full Changelog**:
thomhurst/TUnit@v1.22.6...v1.22.19

## 1.22.6

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

## What's Changed
### Other Changes
* fix: use IComputeResource to filter waitable Aspire resources by
@​thomhurst in thomhurst/TUnit#5278
* fix: preserve StateBag when creating per-test TestBuilderContext by
@​thomhurst in thomhurst/TUnit#5279
### Dependencies
* chore(deps): update tunit to 1.22.3 by @​thomhurst in
thomhurst/TUnit#5275


**Full Changelog**:
thomhurst/TUnit@v1.22.3...v1.22.6

## 1.22.3

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

## What's Changed
### Other Changes
* fix: pass assembly version properties to dotnet pack by @​thomhurst in
thomhurst/TUnit#5274
### Dependencies
* chore(deps): update tunit to 1.22.0 by @​thomhurst in
thomhurst/TUnit#5272


**Full Changelog**:
thomhurst/TUnit@v1.22.0...v1.22.3

## 1.22.0

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

## What's Changed
### Other Changes
* perf: run GitVersion once in CI instead of per-project by @​slang25 in
thomhurst/TUnit#5259
* perf: disable GitVersion MSBuild task globally by @​thomhurst in
thomhurst/TUnit#5266
* fix: skip IResourceWithoutLifetime resources in Aspire fixture wait
logic by @​thomhurst in thomhurst/TUnit#5268
* fix: relax docs site Node.js engine constraint to >=24 by @​thomhurst
in thomhurst/TUnit#5269
* fix: catch unhandled exceptions in ExecuteRequestAsync to prevent IDE
RPC crashes by @​thomhurst in
thomhurst/TUnit#5271
* feat: register HTML report as MTP session artifact by @​thomhurst in
thomhurst/TUnit#5270
### Dependencies
* chore(deps): update tunit to 1.21.30 by @​thomhurst in
thomhurst/TUnit#5254
* chore(deps): update opentelemetry to 1.15.1 by @​thomhurst in
thomhurst/TUnit#5258
* chore(deps): bump node-forge from 1.3.1 to 1.4.0 in /docs by
@​dependabot[bot] in thomhurst/TUnit#5255
* chore(deps): bump picomatch from 2.3.1 to 2.3.2 in /docs by
@​dependabot[bot] in thomhurst/TUnit#5256
* chore(deps): update react by @​thomhurst in
thomhurst/TUnit#5261
* chore(deps): update node.js to >=18.20.8 by @​thomhurst in
thomhurst/TUnit#5262
* chore(deps): update node.js to v24 by @​thomhurst in
thomhurst/TUnit#5264


**Full Changelog**:
thomhurst/TUnit@v1.21.30...v1.22.0

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

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=TUnit&package-manager=nuget&previous-version=1.21.30&new-version=1.23.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>
github-actions bot pushed a commit to IntelliTect/CodingGuidelines that referenced this pull request Mar 30, 2026
Updated [TUnit.Core](https://github.com/thomhurst/TUnit) from 1.21.6 to
1.23.7.

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

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

## 1.23.7

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

## What's Changed
### Other Changes
* feat: use results directory provided by Microsoft Testing Platform in
HtmlReporter by @​DavidZidar in
thomhurst/TUnit#5294
* feat: add benchmarks for Imposter and Mockolate mocking frameworks by
@​vbreuss in thomhurst/TUnit#5295
* feat: add TUnit0080 analyzer for missing polyfill types by @​thomhurst
in thomhurst/TUnit#5292
* fix: respect user-set TUnitImplicitUsings from Directory.Build.props
by @​thomhurst in thomhurst/TUnit#5280
* perf: optimize TUnit.Mocks hot paths by @​thomhurst in
thomhurst/TUnit#5300
### Dependencies
* chore(deps): update tunit to 1.22.19 by @​thomhurst in
thomhurst/TUnit#5296

## New Contributors
* @​DavidZidar made their first contribution in
thomhurst/TUnit#5294

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

## 1.22.19

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

## What's Changed
### Other Changes
* Add mock library benchmarks: TUnit.Mocks vs Moq, NSubstitute,
FakeItEasy by @​Copilot in thomhurst/TUnit#5284
* perf: lazily initialize optional MockEngine collections by @​thomhurst
in thomhurst/TUnit#5289
* Always emit TUnit.Mocks.Generated namespace from source generator by
@​Copilot in thomhurst/TUnit#5282
### Dependencies
* chore(deps): update tunit to 1.22.6 by @​thomhurst in
thomhurst/TUnit#5285


**Full Changelog**:
thomhurst/TUnit@v1.22.6...v1.22.19

## 1.22.6

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

## What's Changed
### Other Changes
* fix: use IComputeResource to filter waitable Aspire resources by
@​thomhurst in thomhurst/TUnit#5278
* fix: preserve StateBag when creating per-test TestBuilderContext by
@​thomhurst in thomhurst/TUnit#5279
### Dependencies
* chore(deps): update tunit to 1.22.3 by @​thomhurst in
thomhurst/TUnit#5275


**Full Changelog**:
thomhurst/TUnit@v1.22.3...v1.22.6

## 1.22.3

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

## What's Changed
### Other Changes
* fix: pass assembly version properties to dotnet pack by @​thomhurst in
thomhurst/TUnit#5274
### Dependencies
* chore(deps): update tunit to 1.22.0 by @​thomhurst in
thomhurst/TUnit#5272


**Full Changelog**:
thomhurst/TUnit@v1.22.0...v1.22.3

## 1.22.0

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

## What's Changed
### Other Changes
* perf: run GitVersion once in CI instead of per-project by @​slang25 in
thomhurst/TUnit#5259
* perf: disable GitVersion MSBuild task globally by @​thomhurst in
thomhurst/TUnit#5266
* fix: skip IResourceWithoutLifetime resources in Aspire fixture wait
logic by @​thomhurst in thomhurst/TUnit#5268
* fix: relax docs site Node.js engine constraint to >=24 by @​thomhurst
in thomhurst/TUnit#5269
* fix: catch unhandled exceptions in ExecuteRequestAsync to prevent IDE
RPC crashes by @​thomhurst in
thomhurst/TUnit#5271
* feat: register HTML report as MTP session artifact by @​thomhurst in
thomhurst/TUnit#5270
### Dependencies
* chore(deps): update tunit to 1.21.30 by @​thomhurst in
thomhurst/TUnit#5254
* chore(deps): update opentelemetry to 1.15.1 by @​thomhurst in
thomhurst/TUnit#5258
* chore(deps): bump node-forge from 1.3.1 to 1.4.0 in /docs by
@​dependabot[bot] in thomhurst/TUnit#5255
* chore(deps): bump picomatch from 2.3.1 to 2.3.2 in /docs by
@​dependabot[bot] in thomhurst/TUnit#5256
* chore(deps): update react by @​thomhurst in
thomhurst/TUnit#5261
* chore(deps): update node.js to >=18.20.8 by @​thomhurst in
thomhurst/TUnit#5262
* chore(deps): update node.js to v24 by @​thomhurst in
thomhurst/TUnit#5264


**Full Changelog**:
thomhurst/TUnit@v1.21.30...v1.22.0

## 1.21.30

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

## What's Changed
### Other Changes
* feat: add test discovery Activity span for tracing by @​thomhurst in
thomhurst/TUnit#5246
* Fix mock generator not preserving nullable annotations on reference
types by @​Copilot in thomhurst/TUnit#5251
* Fix ITestSkippedEventReceiver not firing for [Skip]-attributed tests
by @​thomhurst in thomhurst/TUnit#5253
* Use CallerArgumentExpression for TestDataRow by default. by @​m-gasser
in thomhurst/TUnit#5135
### Dependencies
* chore(deps): update tunit to 1.21.24 by @​thomhurst in
thomhurst/TUnit#5247


**Full Changelog**:
thomhurst/TUnit@v1.21.24...v1.21.30

## 1.21.24

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

## What's Changed
### Other Changes
* Fix OpenTelemetry missing root span by reordering session activity
lifecycle by @​Copilot in thomhurst/TUnit#5245
### Dependencies
* chore(deps): update tunit to 1.21.20 by @​thomhurst in
thomhurst/TUnit#5241
* chore(deps): update dependency stackexchange.redis to 2.12.8 by
@​thomhurst in thomhurst/TUnit#5243


**Full Changelog**:
thomhurst/TUnit@v1.21.20...v1.21.24

## 1.21.20

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

## What's Changed
### Other Changes
* fix: respect TUnitImplicitUsings set in Directory.Build.props by
@​thomhurst in thomhurst/TUnit#5225
* feat: covariant assertions for interfaces and non-sealed classes by
@​thomhurst in thomhurst/TUnit#5226
* feat: support string-to-parseable type conversions in [Arguments] by
@​thomhurst in thomhurst/TUnit#5227
* feat: add string length range assertions by @​thomhurst in
thomhurst/TUnit#4935
* Fix BeforeEvery/AfterEvery hooks for Class and Assembly not being
executed by @​Copilot in thomhurst/TUnit#5239
### Dependencies
* chore(deps): update tunit to 1.21.6 by @​thomhurst in
thomhurst/TUnit#5228
* chore(deps): update dependency gitversion.msbuild to 6.7.0 by
@​thomhurst in thomhurst/TUnit#5229
* chore(deps): update dependency gitversion.tool to v6.7.0 by
@​thomhurst in thomhurst/TUnit#5230
* chore(deps): update aspire to 13.2.0 - autoclosed by @​thomhurst in
thomhurst/TUnit#5232
* chore(deps): update dependency typescript to v6 by @​thomhurst in
thomhurst/TUnit#5233
* chore(deps): update dependency polyfill to 9.23.0 by @​thomhurst in
thomhurst/TUnit#5235
* chore(deps): update dependency polyfill to 9.23.0 by @​thomhurst in
thomhurst/TUnit#5236


**Full Changelog**:
thomhurst/TUnit@v1.21.6...v1.21.20

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

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=TUnit.Core&package-manager=nuget&previous-version=1.21.6&new-version=1.23.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.

Mock Benchmarks

2 participants