Skip to content

fix: invoke inner Func for TestDataRow<Func<T>> data sources (#6161)#6183

Merged
thomhurst merged 1 commit into
mainfrom
fix/6161-testdatarow-func-unwrap
Jun 7, 2026
Merged

fix: invoke inner Func for TestDataRow<Func<T>> data sources (#6161)#6183
thomhurst merged 1 commit into
mainfrom
fix/6161-testdatarow-func-unwrap

Conversation

@thomhurst
Copy link
Copy Markdown
Owner

Problem

Fixes #6161.

A [MethodDataSource] returning IEnumerable<Func<T>> (or IEnumerable<Func<(int,int,int)>>) already invokes the Func and spreads the tuple result across the test method parameters. The same source wrapped as IEnumerable<TestDataRow<Func<T>>> did not — the inner Func was passed through as a single argument. Consequences:

  • The test could only be consumed as TestMethod(Func<...> f), not TestMethod(int a, int b, int c).
  • Parameterized DisplayName placeholders ($arg1, $First, …) couldn't bind to the real values.
  • Because every row's display name collapsed to the same string, the runner treated the rows as duplicates ("runs the first one as many times as the DisplayName is the same").

The behaviour was already implied by the docs (TestDataRow<Func<HttpClient>> "to ensure fresh instances"), so this aligns the code with the documented intent.

Changes

  • TestDataRowUnwrapper.UnwrapArray — invokes the inner Func after unwrapping the TestDataRow, so TestDataRow<Func<T>> behaves identically to a bare Func<T> source (invoke, then spread tuples). This is the single convergence point shared by both source-generated and reflection modes, so there is no codegen change and no snapshot churn.
  • TestDataAnalyzer — strips Func<> and TestDataRow<> wrapper layers in a loop, so TestDataRow<Func<T>> (and Func<TestDataRow<T>>) reduce to the inner T before the tuple check. Prevents a false parameter-count diagnostic that would otherwise block the new pattern at compile time.
  • DisplayNameSubstitutor — word-boundary-aware placeholder replacement, resolving positional $argN before $paramName. Fixes a pre-existing prefix-collision bug where a parameter named a was matched inside $arg1 (rendering 1rg1 instead of 1). This is the bug already documented by CustomDisplayNameTests.TestParameterNamePrefixBug.

Tests

  • TUnit.TestProject/Bugs/6161/Tests.csTestDataRow<Func<(int,int,int)>>(int a, int b, int c) with "$arg1 + $arg2 = $arg3", plus TestDataRow<Func<record>> → single-param. Passes in source-gen and reflection modes; display names render 1 + 1 = 2, 1 + 2 = 3, 2 + 3 = 5. An [After(Class)] hook asserts all three distinct rows ran (dedup regression).
  • MethodDataSourceAnalyzerTests.Method_Data_Source_With_TestDataRow_Func_Tuple_No_Error — no-diagnostic coverage for the inner-Func nesting order.

Verification

  • Source-generator snapshot suite: 118 pass, 0 received-file churn.
  • Public API snapshot: no surface change.
  • Analyzer tests: 47/47. CustomDisplayNameTests: 12/12 (incl. the now-fixed prefix bug).

A [MethodDataSource] returning IEnumerable<Func<T>> invokes the Func and
spreads a tuple result across the test method parameters. The same source
wrapped as IEnumerable<TestDataRow<Func<T>>> did not: the inner Func was
passed through as a single argument, so it could not bind to the test
parameters and parameterized DisplayName placeholders never resolved
(causing rows with the same template to collapse into duplicates).

- TestDataRowUnwrapper.UnwrapArray now invokes the inner Func after
  unwrapping the TestDataRow, so TestDataRow<Func<T>> behaves identically
  to a bare Func<T> source. This is the single convergence point shared by
  both source-generated and reflection modes, so no codegen changes are
  needed.
- TestDataAnalyzer strips Func<> and TestDataRow<> layers in a loop, so
  TestDataRow<Func<T>> (as well as Func<TestDataRow<T>>) reduces to the
  inner type and no longer reports a false parameter-count diagnostic.
- DisplayNameSubstitutor now performs word-boundary-aware placeholder
  replacement and resolves positional $argN before $paramName. This fixes a
  pre-existing prefix-collision bug where a parameter named "a" was matched
  inside "$arg1" (rendering "1rg1"), also covered by the existing
  CustomDisplayNameTests.TestParameterNamePrefixBug.

Adds Bugs/6161 runtime tests (source-gen + reflection) and an analyzer
no-diagnostic test, and documents the tuple + parameterized DisplayName case.
@codacy-production
Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

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-targeted fix for issue #6161. The three changes are cohesive and the root-cause reasoning is sound.

TestDataRowUnwrapper.cs — Core fix

data = DataSourceHelpers.InvokeIfFunc(data);

Placing this right after TryUnwrap is exactly the right spot. The comment correctly identifies why InvokeIfFunc doesn't help for TestDataRow<Func<T>> in DataSourceHelpers.ToObjectArray — the Func is opaque there, only surfacing after the TryUnwrap boundary. Simple and correct.

TestDataAnalyzer.csdo/while loop

The loop approach is elegant. Because both if blocks can fire in the same iteration, Func<TestDataRow<T>> collapses to T in a single pass rather than requiring a second loop. Safe against infinite iteration since C# generics cannot form cycles — each iteration necessarily moves inward.

One observation: isFunc is set to true on any Func<> peel, including a second peel in a subsequent iteration (e.g., Func<Func<T>>). This is consistent with the existing semantics of isFunc — it signals that tuple-spread applies — which is correct for any Func in the chain. Not a bug, just worth being aware of.

DisplayNameSubstitutor.csReplacePlaceholder + ordering fix

Ordering change (positional before named): Correct. Without this, $a (named param) matches the $a prefix inside $arg1, corrupting the output before the positional pass ever runs.

ReplacePlaceholder boundary check: The word-boundary logic is correct. I traced through the $arg1 / $arg10 interaction manually — $arg1 inside $arg10 is correctly skipped (the 0 after $arg1 is an identifier char), while standalone $arg1 is replaced.

One minor edge case to be aware of: since IsIdentifierChar includes _, a display name template like "$a_description" where a is a parameter name will not substitute $a there (because _ counts as an identifier char following $a). This is actually the correct/expected behavior in C# identifier semantics — a_description would be a different name — but users who write $a_suffix expecting $a to be replaced will be surprised. Not a regression from this PR, and the behavior is defensible; just worth documenting if it surfaces as a user complaint.

Potential substitution-order collision: If a user names a parameter arg1, the positional pass resolves $arg1 first (as the first argument's value), and the named pass for parameters[0] (named arg1) then searches for $arg1 in the already-substituted string. In practice this won't matter because the positional value is unlikely to re-introduce $arg1, but it's a latent edge case in any linear-substitution scheme.

Test coverage

The [After(Class)] deduplication guard in Tests.cs is a particularly good regression anchor — it directly tests the symptom that motivated the bug report (multiple rows collapsing to a single execution). The combination of tuple and reference-type test cases (TupleFuncIsUnwrapped / ReferenceFuncIsUnwrapped) is thorough.

Documentation

The doc addition accurately describes the behavior and the code example matches the regression test, which is a nice consistency detail.


Overall: The fix is correct, well-tested, and the implementation choices are sound. No blocking concerns — the edge cases noted above are pre-existing design tradeoffs rather than regressions. Good work.

@thomhurst thomhurst enabled auto-merge (squash) June 7, 2026 20:49
@thomhurst thomhurst merged commit 391a76a into main Jun 7, 2026
16 checks passed
@thomhurst thomhurst deleted the fix/6161-testdatarow-func-unwrap branch June 7, 2026 21:07
This was referenced Jun 8, 2026
github-actions Bot pushed a commit to BenjaminMichaelis/TrxLib that referenced this pull request Jun 8, 2026
Updated [TUnit](https://github.com/thomhurst/TUnit) from 1.48.6 to
1.51.0.

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

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

## 1.51.0

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

## What's Changed
### Other Changes
* fix(mocks): WasCalled/WasNeverCalled assertions via
[GenerateAssertion] for all ICallVerification types by @​thomhurst in
thomhurst/TUnit#6176
* fix: create fresh non-shared instances per CombinedDataSources
combination by @​thomhurst in
thomhurst/TUnit#6179
* fix: assign TestDetails before TestContext is published to
ClassHookContext.Tests by @​thomhurst in
thomhurst/TUnit#6182
* fix: resolve inherited instance data source members for
MethodDataSource by @​thomhurst in
thomhurst/TUnit#6178
* feat(mocks): per-element matchers for params array parameters by
@​thomhurst in thomhurst/TUnit#6181
* fix: invoke inner Func for TestDataRow<Func<T>> data sources (#​6161)
by @​thomhurst in thomhurst/TUnit#6183
### Dependencies
* chore(deps): update _tunitpolyfillversion to 10.8.0 by @​thomhurst in
thomhurst/TUnit#6167
* chore(deps): update dependency azure.storage.blobs to 12.29.0 by
@​thomhurst in thomhurst/TUnit#6168
* chore(deps): update aspire by @​thomhurst in
thomhurst/TUnit#6165
* chore(deps): update dependency cliwrap to 3.10.2 by @​thomhurst in
thomhurst/TUnit#6166
* chore(deps): update dependency streamjsonrpc to 2.25.25 by @​thomhurst
in thomhurst/TUnit#6170
* chore(deps): update dependency polyfill to 10.8.0 by @​thomhurst in
thomhurst/TUnit#6169
* chore(deps): update tunit to 1.5* by @​thomhurst in
thomhurst/TUnit#6171
* chore(deps): update _tunitpolyfillversion to 10.8.1 by @​thomhurst in
thomhurst/TUnit#6174
* chore(deps): update dependency polyfill to 10.8.1 by @​thomhurst in
thomhurst/TUnit#6175


**Full Changelog**:
thomhurst/TUnit@v1.50.0...v1.51.0

## 1.50.0

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

## What's Changed
### Other Changes
* fix(analyzers): decouple code fixers from Rules to prevent
MissingFieldException in VS by @​thomhurst in
thomhurst/TUnit#6158
* Fix mock wrappers for indexers and generic methods by @​thomhurst in
thomhurst/TUnit#6163
* Add global mock default mode by @​thomhurst in
thomhurst/TUnit#6164


**Full Changelog**:
thomhurst/TUnit@v1.49.0...v1.50.0

## 1.49.0

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

## What's Changed
### Other Changes
* docs: benchmark page descriptions + promote Benchmarks in sidebar by
@​thomhurst in thomhurst/TUnit#6143
* feat(mocks): discriminate generic-method mocks by type argument by
@​thomhurst in thomhurst/TUnit#6153
* fix(source-gen): jagged array data fails to compile (#​6150) by
@​thomhurst in thomhurst/TUnit#6152
* fix: dispose shared fixtures when only a subset of consuming tests
runs by @​thomhurst in thomhurst/TUnit#6156
### Dependencies
* chore(deps): update tunit to 1.48.6 by @​thomhurst in
thomhurst/TUnit#6142
* chore(deps): update react to ^19.2.7 by @​thomhurst in
thomhurst/TUnit#6144
* chore(deps): update aspire to 13.4.0 by @​thomhurst in
thomhurst/TUnit#6145
* chore(deps): update dependency nunit.analyzers to 4.14.0 by
@​thomhurst in thomhurst/TUnit#6146
* chore(deps): update dependency polyfill to 10.7.2 by @​thomhurst in
thomhurst/TUnit#6148
* chore(deps): update dependency polyfill to 10.7.2 by @​thomhurst in
thomhurst/TUnit#6149
* chore(deps): update dependency dompurify to v3.4.8 by @​thomhurst in
thomhurst/TUnit#6155


**Full Changelog**:
thomhurst/TUnit@v1.48.6...v1.49.0

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

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=TUnit&package-manager=nuget&previous-version=1.48.6&new-version=1.51.0)](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 BenjaminMichaelis/DotnetTemplates that referenced this pull request Jun 8, 2026
Updated [TUnit](https://github.com/thomhurst/TUnit) from 1.45.0 to
1.51.0.

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

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

## 1.51.0

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

## What's Changed
### Other Changes
* fix(mocks): WasCalled/WasNeverCalled assertions via
[GenerateAssertion] for all ICallVerification types by @​thomhurst in
thomhurst/TUnit#6176
* fix: create fresh non-shared instances per CombinedDataSources
combination by @​thomhurst in
thomhurst/TUnit#6179
* fix: assign TestDetails before TestContext is published to
ClassHookContext.Tests by @​thomhurst in
thomhurst/TUnit#6182
* fix: resolve inherited instance data source members for
MethodDataSource by @​thomhurst in
thomhurst/TUnit#6178
* feat(mocks): per-element matchers for params array parameters by
@​thomhurst in thomhurst/TUnit#6181
* fix: invoke inner Func for TestDataRow<Func<T>> data sources (#​6161)
by @​thomhurst in thomhurst/TUnit#6183
### Dependencies
* chore(deps): update _tunitpolyfillversion to 10.8.0 by @​thomhurst in
thomhurst/TUnit#6167
* chore(deps): update dependency azure.storage.blobs to 12.29.0 by
@​thomhurst in thomhurst/TUnit#6168
* chore(deps): update aspire by @​thomhurst in
thomhurst/TUnit#6165
* chore(deps): update dependency cliwrap to 3.10.2 by @​thomhurst in
thomhurst/TUnit#6166
* chore(deps): update dependency streamjsonrpc to 2.25.25 by @​thomhurst
in thomhurst/TUnit#6170
* chore(deps): update dependency polyfill to 10.8.0 by @​thomhurst in
thomhurst/TUnit#6169
* chore(deps): update tunit to 1.5* by @​thomhurst in
thomhurst/TUnit#6171
* chore(deps): update _tunitpolyfillversion to 10.8.1 by @​thomhurst in
thomhurst/TUnit#6174
* chore(deps): update dependency polyfill to 10.8.1 by @​thomhurst in
thomhurst/TUnit#6175


**Full Changelog**:
thomhurst/TUnit@v1.50.0...v1.51.0

## 1.50.0

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

## What's Changed
### Other Changes
* fix(analyzers): decouple code fixers from Rules to prevent
MissingFieldException in VS by @​thomhurst in
thomhurst/TUnit#6158
* Fix mock wrappers for indexers and generic methods by @​thomhurst in
thomhurst/TUnit#6163
* Add global mock default mode by @​thomhurst in
thomhurst/TUnit#6164


**Full Changelog**:
thomhurst/TUnit@v1.49.0...v1.50.0

## 1.49.0

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

## What's Changed
### Other Changes
* docs: benchmark page descriptions + promote Benchmarks in sidebar by
@​thomhurst in thomhurst/TUnit#6143
* feat(mocks): discriminate generic-method mocks by type argument by
@​thomhurst in thomhurst/TUnit#6153
* fix(source-gen): jagged array data fails to compile (#​6150) by
@​thomhurst in thomhurst/TUnit#6152
* fix: dispose shared fixtures when only a subset of consuming tests
runs by @​thomhurst in thomhurst/TUnit#6156
### Dependencies
* chore(deps): update tunit to 1.48.6 by @​thomhurst in
thomhurst/TUnit#6142
* chore(deps): update react to ^19.2.7 by @​thomhurst in
thomhurst/TUnit#6144
* chore(deps): update aspire to 13.4.0 by @​thomhurst in
thomhurst/TUnit#6145
* chore(deps): update dependency nunit.analyzers to 4.14.0 by
@​thomhurst in thomhurst/TUnit#6146
* chore(deps): update dependency polyfill to 10.7.2 by @​thomhurst in
thomhurst/TUnit#6148
* chore(deps): update dependency polyfill to 10.7.2 by @​thomhurst in
thomhurst/TUnit#6149
* chore(deps): update dependency dompurify to v3.4.8 by @​thomhurst in
thomhurst/TUnit#6155


**Full Changelog**:
thomhurst/TUnit@v1.48.6...v1.49.0

## 1.48.6

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

## What's Changed
### Other Changes
* fix(sourcegen): fully-qualify Linq calls in params array binding
(#​6140) by @​thomhurst in thomhurst/TUnit#6141
### Dependencies
* chore(deps): update tunit to 1.48.0 by @​thomhurst in
thomhurst/TUnit#6135
* chore(deps): update dependency polyfill to 10.7.1 by @​thomhurst in
thomhurst/TUnit#6137
* chore(deps): update dependency polyfill to 10.7.1 by @​thomhurst in
thomhurst/TUnit#6138
* chore(deps): update verify to 31.19.0 by @​thomhurst in
thomhurst/TUnit#6139


**Full Changelog**:
thomhurst/TUnit@v1.48.0...v1.48.6

## 1.48.0

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

## What's Changed
### Other Changes
* feat(html-report): baked-in C# syntax highlighting on Source tab by
@​slang25 in thomhurst/TUnit#6132
* feat(analyzers): suppress VSTHRD200 on test and hook methods by
@​thomhurst in thomhurst/TUnit#6123
* fix(source-gen): correct source location for cross-project inherited
tests by @​slang25 in thomhurst/TUnit#6133
* feat(assertions): add WasCalled to tunit mocks assertions by
@​robertcoltheart in thomhurst/TUnit#6126
* feat(arguments): bind array values to a single array test parameter by
@​thomhurst in thomhurst/TUnit#6122
* fix: populate retry/flaky attempt history in HTML report (#​6119) by
@​thomhurst in thomhurst/TUnit#6124
### Dependencies
* chore(deps): update tunit to 1.47.0 by @​thomhurst in
thomhurst/TUnit#6115
* chore(deps): update dependency
microsoft.visualstudio.threading.analyzers to 17.14.15 by @​thomhurst in
thomhurst/TUnit#6134


**Full Changelog**:
thomhurst/TUnit@v1.47.0...v1.48.0

## 1.47.0

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

## What's Changed
### Other Changes
* perf(engine): hoist GetParameters and dict-dedup AfterTestDiscovery
hooks by @​thomhurst in thomhurst/TUnit#6062
* perf(engine): hoist GetParameters and drop LINQ in reflection
discovery by @​thomhurst in thomhurst/TUnit#6063
* perf(engine): cache treenode filter path on TestMetadata by
@​thomhurst in thomhurst/TUnit#6064
* perf: use is T pattern in ReflectionExtensions.HasAttribute fallback
(#​6060) by @​thomhurst in thomhurst/TUnit#6066
* perf: replace OrderBy().ToArray() with Array.Sort in
ConstraintKeyScheduler by @​thomhurst in
thomhurst/TUnit#6067
* perf: pool HashSet in WaitingTestIndex.GetCandidatesForReleasedKeys by
@​thomhurst in thomhurst/TUnit#6069
* perf: collapse OfType chains in JUnitXmlWriter (#​6052) by @​thomhurst
in thomhurst/TUnit#6070
* perf(engine): avoid closure allocation in
AfterHookPairTracker.GetOrCreateAfterAssemblyTask (#​6041) by
@​thomhurst in thomhurst/TUnit#6071
* perf: avoid closure allocation in
BeforeHookTaskCache.GetOrCreateBeforeAssemblyTask (#​6040) by
@​thomhurst in thomhurst/TUnit#6073
* perf: use TryAdd in TestDependencyResolver dependency dedupe by
@​thomhurst in thomhurst/TUnit#6068
* perf: replace LINQ Any with foreach in TestGenericTypeResolver
(#​6044) by @​thomhurst in thomhurst/TUnit#6072
* perf: avoid Cast<object>().FirstOrDefault() iterator alloc in
CastHelper (#​6029) by @​thomhurst in
thomhurst/TUnit#6074
* perf(engine): avoid string round-trip when building nested type names
(#​6049) by @​thomhurst in thomhurst/TUnit#6075
* perf(engine): replace Select+ToArray with manual Type[] build (#​6043)
by @​thomhurst in thomhurst/TUnit#6076
* perf(core): replace OfType().FirstOrDefault()/.Any() with foreach in
ClassConstructorHelper by @​thomhurst in
thomhurst/TUnit#6078
* perf(engine): avoid FirstOrDefault iterator alloc in
TestGenericTypeResolver by @​thomhurst in
thomhurst/TUnit#6079
* perf(engine): use SearchValues<char> for reporter filename
sanitization by @​thomhurst in
thomhurst/TUnit#6090
* perf: dedupe TestDataFormatter.FormatArguments with pooled
StringBuilder by @​thomhurst in
thomhurst/TUnit#6088
* perf(engine): use MemoryExtensions.Split for path parsing in
MetadataFilterMatcher by @​thomhurst in
thomhurst/TUnit#6085
* perf(engine): use CollectionsMarshal.GetValueRefOrAddDefault for
dictionary index builds by @​thomhurst in
thomhurst/TUnit#6086
* perf(engine): replace LINQ Where closure with inline filter in
MetadataDependencyExpander BFS by @​thomhurst in
thomhurst/TUnit#6084
* perf(engine): pool StringBuilder in DisplayNameBuilder.FormatArguments
by @​thomhurst in thomhurst/TUnit#6082
* Preserve specialized chaining after null assertions by @​thomhurst in
thomhurst/TUnit#6008
* perf: use EnumerateLines for line splitting in HtmlReportGenerator by
@​thomhurst in thomhurst/TUnit#6089
* perf: collapse Replace chain in TestNameFormatter.BuildTestId by
@​thomhurst in thomhurst/TUnit#6083
* perf: use OrdinalIgnoreCase Contains in HtmlReportGenerator span
mapping by @​thomhurst in thomhurst/TUnit#6093
* perf(assertions): avoid eager interpolated-string alloc in assertion
source ctors by @​thomhurst in
thomhurst/TUnit#6091
* perf: optimize TestNameFormatter argument and bool formatting by
@​thomhurst in thomhurst/TUnit#6095
* perf: use FrozenSet/FrozenDictionary for read-only static lookups by
@​thomhurst in thomhurst/TUnit#6099
* perf: avoid GetCustomAttributes() + LINQ chain for per-property
attribute scans by @​thomhurst in
thomhurst/TUnit#6098
* perf(engine): replace magic-string RequiredAttribute match with type
check in ConstructorHelper by @​thomhurst in
thomhurst/TUnit#6087
* perf(core): replace Select+Func factory chain in DataSourceHelpers by
@​thomhurst in thomhurst/TUnit#6081
* perf: replace LINQ dependency extraction with manual loop by
@​thomhurst in thomhurst/TUnit#6096
* perf(core): avoid string[] alloc in ArgumentFormatter.FormatArguments
by @​thomhurst in thomhurst/TUnit#6080
* perf: use [GeneratedRegex] in MetadataFilterMatcher by @​thomhurst in
thomhurst/TUnit#6094
* perf: dedupe GetSimpleTypeName into shared TypeNameFormatter by
@​thomhurst in thomhurst/TUnit#6097
* fix: remove GitVersion MSBuild task, pin local builds to 99.99.99
(#​6077) by @​thomhurst in thomhurst/TUnit#6101
* HTML Report: source link + code snippet on Source tab (#​5993) by
@​thomhurst in thomhurst/TUnit#6100
* perf(sourcegen): Single-pass attribute classification by @​thomhurst
in thomhurst/TUnit#6111
* perf(core): eliminate per-test allocations in TestDetails/HookMethod
by @​thomhurst in thomhurst/TUnit#6109
* perf: hoist char[] alloc in FsCheckPropertyTestExecutor to static
SearchValues by @​thomhurst in
thomhurst/TUnit#6108
* perf(core): de-LINQ data-source expansion by @​thomhurst in
thomhurst/TUnit#6110
* perf: avoid LINQ chains in TestDependency equality and
MethodDataSourceAttribute method matching by @​thomhurst in
thomhurst/TUnit#6092
* perf(engine): reduce allocations in reflection-mode
discovery/execution by @​thomhurst in
thomhurst/TUnit#6113
* perf(assertions): allocation-free passing path (TUnit.Assertions) by
@​thomhurst in thomhurst/TUnit#6112
### Dependencies
 ... (truncated)

## 1.46.0

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

## What's Changed
### Other Changes
* docs: add Rider VSTest conflict troubleshooting by @​smolchanovsky in
thomhurst/TUnit#5989
* Populate generated test metadata with full source spans by @​Copilot
in thomhurst/TUnit#5991
* Add devcontainer configuration by @​Copilot in
thomhurst/TUnit#5995
* fix: treenode filter pre-filter rejects parenthesised segments
(#​6026) by @​thomhurst in thomhurst/TUnit#6027
* fix(engine): isolate per-session state under MTP server-mode
concurrency (#​6001) by @​thomhurst in
thomhurst/TUnit#6025
### Dependencies
* chore(deps): update dependency stackexchange.redis to 2.13.10 by
@​thomhurst in thomhurst/TUnit#5985
* chore(deps): update tunit to 1.45.29 by @​thomhurst in
thomhurst/TUnit#5986
* chore(deps): update dependency mockolate to 3.2.1 by @​thomhurst in
thomhurst/TUnit#5987
* chore(deps): update dependency microsoft.playwright to 1.60.0 by
@​thomhurst in thomhurst/TUnit#5988
* chore(deps): update dependency messagepack to 3.1.6 by @​thomhurst in
thomhurst/TUnit#5992
* chore(deps): update dependency polyfill to 10.7.0 by @​thomhurst in
thomhurst/TUnit#5998
* chore(deps): update dependency polyfill to 10.7.0 by @​thomhurst in
thomhurst/TUnit#5997
* chore(deps): update verify to 31.17.0 by @​thomhurst in
thomhurst/TUnit#6000
* chore(deps): update verify to 31.18.0 by @​thomhurst in
thomhurst/TUnit#6013
* chore(deps): update dependency microsoft.net.test.sdk to 18.6.0 by
@​thomhurst in thomhurst/TUnit#6016
* chore(deps): update dependency dompurify to v3.4.6 by @​thomhurst in
thomhurst/TUnit#6015
* chore(deps): update dependency dompurify to v3.4.7 by @​thomhurst in
thomhurst/TUnit#6019
* chore(deps): update dependency npgsql to 10.0.3 by @​thomhurst in
thomhurst/TUnit#6020
* chore(deps): update dependency stackexchange.redis to 2.13.17 by
@​thomhurst in thomhurst/TUnit#6021
* chore(deps): update dependency npgsql.entityframeworkcore.postgresql
to 10.0.2 by @​thomhurst in thomhurst/TUnit#6022

## New Contributors
* @​smolchanovsky made their first contribution in
thomhurst/TUnit#5989

**Full Changelog**:
thomhurst/TUnit@v1.45.29...v1.46.0

## 1.45.29

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

## What's Changed
### Other Changes
* Fix shared fixture lifetime for reused discovery instances by
@​thomhurst in thomhurst/TUnit#5983
* Preserve override accessibility in generated mocks by @​thomhurst in
thomhurst/TUnit#5984
### Dependencies
* chore(deps): update tunit to 1.45.22 by @​thomhurst in
thomhurst/TUnit#5974
* chore(deps): update dependency messagepack to 3.1.5 by @​thomhurst in
thomhurst/TUnit#5978
* chore(deps): update aspire to 13.3.5 by @​thomhurst in
thomhurst/TUnit#5980


**Full Changelog**:
thomhurst/TUnit@v1.45.22...v1.45.29

## 1.45.22

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

## What's Changed
### Other Changes
* Remove ".NET" from Aspire references by @​antmdvs in
thomhurst/TUnit#5968
* Fix chained mock setup behavior by @​thomhurst in
thomhurst/TUnit#5973
### Dependencies
* chore(deps): update tunit to 1.45.8 by @​thomhurst in
thomhurst/TUnit#5958
* chore(deps): update dependency nunit to 4.6.1 by @​thomhurst in
thomhurst/TUnit#5961
* chore(deps): update dependency testcontainers.postgresql to 4.12.0 by
@​thomhurst in thomhurst/TUnit#5963
* chore(deps): update dependency testcontainers.redis to 4.12.0 by
@​thomhurst in thomhurst/TUnit#5965
* chore(deps): update dependency testcontainers.kafka to 4.12.0 by
@​thomhurst in thomhurst/TUnit#5962
* chore(deps): update aspire to 13.3.4 by @​thomhurst in
thomhurst/TUnit#5966
* chore(deps): bump webpack-dev-server from 5.2.2 to 5.2.4 in /docs by
@​dependabot[bot] in thomhurst/TUnit#5964

## New Contributors
* @​antmdvs made their first contribution in
thomhurst/TUnit#5968

**Full Changelog**:
thomhurst/TUnit@v1.45.8...v1.45.22

## 1.45.8

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

## What's Changed
### Other Changes
* fix(aspire): route CreateHttpClient through IHttpClientFactory by
@​thomhurst in thomhurst/TUnit#5957
### Dependencies
* chore(deps): update tunit to 1.45.0 by @​thomhurst in
thomhurst/TUnit#5949
* chore(deps): update dependency dompurify to v3.4.5 by @​thomhurst in
thomhurst/TUnit#5951
* chore(deps): update dependency
microsoft.testing.extensions.codecoverage to 18.7.0 by @​thomhurst in
thomhurst/TUnit#5953
* chore(deps): update dependency coverlet.collector to 10.0.1 by
@​thomhurst in thomhurst/TUnit#5952
* chore(deps): update dependency polyfill to 10.6.0 by @​thomhurst in
thomhurst/TUnit#5955
* chore(deps): update dependency polyfill to 10.6.0 by @​thomhurst in
thomhurst/TUnit#5954


**Full Changelog**:
thomhurst/TUnit@v1.45.0...v1.45.8

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

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=TUnit&package-manager=nuget&previous-version=1.45.0&new-version=1.51.0)](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>
intellitect-bot pushed a commit to IntelliTect/EssentialCSharp.Web that referenced this pull request Jun 8, 2026
Updated [TUnit](https://github.com/thomhurst/TUnit) from 1.49.0 to
1.51.0.

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

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

## 1.51.0

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

## What's Changed
### Other Changes
* fix(mocks): WasCalled/WasNeverCalled assertions via
[GenerateAssertion] for all ICallVerification types by @​thomhurst in
thomhurst/TUnit#6176
* fix: create fresh non-shared instances per CombinedDataSources
combination by @​thomhurst in
thomhurst/TUnit#6179
* fix: assign TestDetails before TestContext is published to
ClassHookContext.Tests by @​thomhurst in
thomhurst/TUnit#6182
* fix: resolve inherited instance data source members for
MethodDataSource by @​thomhurst in
thomhurst/TUnit#6178
* feat(mocks): per-element matchers for params array parameters by
@​thomhurst in thomhurst/TUnit#6181
* fix: invoke inner Func for TestDataRow<Func<T>> data sources (#​6161)
by @​thomhurst in thomhurst/TUnit#6183
### Dependencies
* chore(deps): update _tunitpolyfillversion to 10.8.0 by @​thomhurst in
thomhurst/TUnit#6167
* chore(deps): update dependency azure.storage.blobs to 12.29.0 by
@​thomhurst in thomhurst/TUnit#6168
* chore(deps): update aspire by @​thomhurst in
thomhurst/TUnit#6165
* chore(deps): update dependency cliwrap to 3.10.2 by @​thomhurst in
thomhurst/TUnit#6166
* chore(deps): update dependency streamjsonrpc to 2.25.25 by @​thomhurst
in thomhurst/TUnit#6170
* chore(deps): update dependency polyfill to 10.8.0 by @​thomhurst in
thomhurst/TUnit#6169
* chore(deps): update tunit to 1.5* by @​thomhurst in
thomhurst/TUnit#6171
* chore(deps): update _tunitpolyfillversion to 10.8.1 by @​thomhurst in
thomhurst/TUnit#6174
* chore(deps): update dependency polyfill to 10.8.1 by @​thomhurst in
thomhurst/TUnit#6175


**Full Changelog**:
thomhurst/TUnit@v1.50.0...v1.51.0

## 1.50.0

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

## What's Changed
### Other Changes
* fix(analyzers): decouple code fixers from Rules to prevent
MissingFieldException in VS by @​thomhurst in
thomhurst/TUnit#6158
* Fix mock wrappers for indexers and generic methods by @​thomhurst in
thomhurst/TUnit#6163
* Add global mock default mode by @​thomhurst in
thomhurst/TUnit#6164


**Full Changelog**:
thomhurst/TUnit@v1.49.0...v1.50.0

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

Updated [TUnit.AspNetCore](https://github.com/thomhurst/TUnit) from
1.49.0 to 1.51.0.

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

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

## 1.51.0

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

## What's Changed
### Other Changes
* fix(mocks): WasCalled/WasNeverCalled assertions via
[GenerateAssertion] for all ICallVerification types by @​thomhurst in
thomhurst/TUnit#6176
* fix: create fresh non-shared instances per CombinedDataSources
combination by @​thomhurst in
thomhurst/TUnit#6179
* fix: assign TestDetails before TestContext is published to
ClassHookContext.Tests by @​thomhurst in
thomhurst/TUnit#6182
* fix: resolve inherited instance data source members for
MethodDataSource by @​thomhurst in
thomhurst/TUnit#6178
* feat(mocks): per-element matchers for params array parameters by
@​thomhurst in thomhurst/TUnit#6181
* fix: invoke inner Func for TestDataRow<Func<T>> data sources (#​6161)
by @​thomhurst in thomhurst/TUnit#6183
### Dependencies
* chore(deps): update _tunitpolyfillversion to 10.8.0 by @​thomhurst in
thomhurst/TUnit#6167
* chore(deps): update dependency azure.storage.blobs to 12.29.0 by
@​thomhurst in thomhurst/TUnit#6168
* chore(deps): update aspire by @​thomhurst in
thomhurst/TUnit#6165
* chore(deps): update dependency cliwrap to 3.10.2 by @​thomhurst in
thomhurst/TUnit#6166
* chore(deps): update dependency streamjsonrpc to 2.25.25 by @​thomhurst
in thomhurst/TUnit#6170
* chore(deps): update dependency polyfill to 10.8.0 by @​thomhurst in
thomhurst/TUnit#6169
* chore(deps): update tunit to 1.5* by @​thomhurst in
thomhurst/TUnit#6171
* chore(deps): update _tunitpolyfillversion to 10.8.1 by @​thomhurst in
thomhurst/TUnit#6174
* chore(deps): update dependency polyfill to 10.8.1 by @​thomhurst in
thomhurst/TUnit#6175


**Full Changelog**:
thomhurst/TUnit@v1.50.0...v1.51.0

## 1.50.0

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

## What's Changed
### Other Changes
* fix(analyzers): decouple code fixers from Rules to prevent
MissingFieldException in VS by @​thomhurst in
thomhurst/TUnit#6158
* Fix mock wrappers for indexers and generic methods by @​thomhurst in
thomhurst/TUnit#6163
* Add global mock default mode by @​thomhurst in
thomhurst/TUnit#6164


**Full Changelog**:
thomhurst/TUnit@v1.49.0...v1.50.0

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

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 Jun 8, 2026
Updated [TUnit.Core](https://github.com/thomhurst/TUnit) from 1.48.6 to
1.51.0.

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

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

## 1.51.0

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

## What's Changed
### Other Changes
* fix(mocks): WasCalled/WasNeverCalled assertions via
[GenerateAssertion] for all ICallVerification types by @​thomhurst in
thomhurst/TUnit#6176
* fix: create fresh non-shared instances per CombinedDataSources
combination by @​thomhurst in
thomhurst/TUnit#6179
* fix: assign TestDetails before TestContext is published to
ClassHookContext.Tests by @​thomhurst in
thomhurst/TUnit#6182
* fix: resolve inherited instance data source members for
MethodDataSource by @​thomhurst in
thomhurst/TUnit#6178
* feat(mocks): per-element matchers for params array parameters by
@​thomhurst in thomhurst/TUnit#6181
* fix: invoke inner Func for TestDataRow<Func<T>> data sources (#​6161)
by @​thomhurst in thomhurst/TUnit#6183
### Dependencies
* chore(deps): update _tunitpolyfillversion to 10.8.0 by @​thomhurst in
thomhurst/TUnit#6167
* chore(deps): update dependency azure.storage.blobs to 12.29.0 by
@​thomhurst in thomhurst/TUnit#6168
* chore(deps): update aspire by @​thomhurst in
thomhurst/TUnit#6165
* chore(deps): update dependency cliwrap to 3.10.2 by @​thomhurst in
thomhurst/TUnit#6166
* chore(deps): update dependency streamjsonrpc to 2.25.25 by @​thomhurst
in thomhurst/TUnit#6170
* chore(deps): update dependency polyfill to 10.8.0 by @​thomhurst in
thomhurst/TUnit#6169
* chore(deps): update tunit to 1.5* by @​thomhurst in
thomhurst/TUnit#6171
* chore(deps): update _tunitpolyfillversion to 10.8.1 by @​thomhurst in
thomhurst/TUnit#6174
* chore(deps): update dependency polyfill to 10.8.1 by @​thomhurst in
thomhurst/TUnit#6175


**Full Changelog**:
thomhurst/TUnit@v1.50.0...v1.51.0

## 1.50.0

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

## What's Changed
### Other Changes
* fix(analyzers): decouple code fixers from Rules to prevent
MissingFieldException in VS by @​thomhurst in
thomhurst/TUnit#6158
* Fix mock wrappers for indexers and generic methods by @​thomhurst in
thomhurst/TUnit#6163
* Add global mock default mode by @​thomhurst in
thomhurst/TUnit#6164


**Full Changelog**:
thomhurst/TUnit@v1.49.0...v1.50.0

## 1.49.0

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

## What's Changed
### Other Changes
* docs: benchmark page descriptions + promote Benchmarks in sidebar by
@​thomhurst in thomhurst/TUnit#6143
* feat(mocks): discriminate generic-method mocks by type argument by
@​thomhurst in thomhurst/TUnit#6153
* fix(source-gen): jagged array data fails to compile (#​6150) by
@​thomhurst in thomhurst/TUnit#6152
* fix: dispose shared fixtures when only a subset of consuming tests
runs by @​thomhurst in thomhurst/TUnit#6156
### Dependencies
* chore(deps): update tunit to 1.48.6 by @​thomhurst in
thomhurst/TUnit#6142
* chore(deps): update react to ^19.2.7 by @​thomhurst in
thomhurst/TUnit#6144
* chore(deps): update aspire to 13.4.0 by @​thomhurst in
thomhurst/TUnit#6145
* chore(deps): update dependency nunit.analyzers to 4.14.0 by
@​thomhurst in thomhurst/TUnit#6146
* chore(deps): update dependency polyfill to 10.7.2 by @​thomhurst in
thomhurst/TUnit#6148
* chore(deps): update dependency polyfill to 10.7.2 by @​thomhurst in
thomhurst/TUnit#6149
* chore(deps): update dependency dompurify to v3.4.8 by @​thomhurst in
thomhurst/TUnit#6155


**Full Changelog**:
thomhurst/TUnit@v1.48.6...v1.49.0

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

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

[Feature]: Method Data Source: Match functionality of IEnumerable<TestDataRow<Func<>>> with IEnumerable<Func<>>

1 participant