Fix Type assignability assertions to evaluate represented type (not RuntimeType) - #6711
Conversation
Co-authored-by: thomhurst <30480171+thomhurst@users.noreply.github.com>
Type assignability assertions to evaluate represented type (not RuntimeType)
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 38b97aab7a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Greptile SummaryThe PR makes direct
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| src/TUnit.Assertions/Conditions/TypeAssertionExtensions.cs | Adds generated runtime-Type assignability assertions with explicit null-argument failures. |
| src/TUnit.Assertions/Conditions/TypeOfAssertion.cs | Adds represented-type semantics to the relevant generic assignability assertion implementations. |
| src/TUnit.Assertions/Extensions/Assert.cs | Introduces and prioritizes the specialized assertion entry point for nullable Type values. |
| src/TUnit.Assertions/Sources/TypeValueAssertion.cs | Defines the direct Type assertion source and its represented-type generic assignability methods. |
| tests/TUnit.Assertions.Tests/TypeAssertionTests.cs | Covers direct generic, runtime-Type, TypeInfo, null-argument, chaining, and generic-source behavior. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
A["Assert.That(typeof(Dog))"] --> B["TypeValueAssertion"]
B --> C{"Assignability overload"}
C -->|"Generic target"| D["typeof(Target).IsAssignableFrom(typeof(Dog))"]
C -->|"Runtime Type target"| E["expectedType.IsAssignableFrom(typeof(Dog))"]
D --> F["Assertion result"]
E --> F
Reviews (7): Last reviewed commit: "fix(assertions): prioritize Type overloa..." | Re-trigger Greptile
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2ae67b7490
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Code ReviewI reviewed this PR by tracing the fix's design and empirically verifying findings by building the branch and running targeted repro tests. The core goal — making 1. Fix only covers the direct entry point, not indirect chains (confirmed by test)
Verified directly: Animal? result = await Assert.That(typeof(Dog)).IsClass().And.IsAssignableTo<Animal>();
// assertion passes, but result == null (confirmed via test run: RESULT_IS_NULL=True)Why this matters: 2. Missing null-check on new Type-targeted overloads (confirmed by test)
The new Verified directly: await Assert.That(typeof(Dog)).IsAssignableTo(null!);
// throws raw System.NullReferenceException instead of a graceful assertion failure (EXCEPTION_TYPE=System.NullReferenceException)Why this matters: every other TUnit assertion fails gracefully with a clear assertion message on invalid input; a raw NRE breaks that contract and gives users a confusing stack trace instead of an assertion failure message pointing at the actual mistake. 3. Shared base-class fix may widen behavior beyond
|
Code review (follow-up)I checked the current head ( 1. Gap 2 (missing null-check) — still unaddressedTUnit/src/TUnit.Assertions/Conditions/TypeAssertionExtensions.cs Lines 86 to 98 in 8e58dc6
2. Gap 1 (indirect
|
Assert.That(typeof(Dog)).IsAssignableTo<Animal>()was evaluating the runtime type of theTypeinstance (RuntimeType) rather than the represented type (Dog), causing valid assignability checks to fail. This PR alignsTypeassignability behavior with documented usage.Assertion semantics fix
Typevalues as the target of assignability checks.IsAssignableTo<T>()andIsAssignableFrom<T>()paths when the asserted value is aType.Type-specific API surface (generator-backed)
Type-targeted overloads using assertion generation:IsAssignableTo(this Type value, Type expectedType)IsAssignableFrom(this Type value, Type sourceType)TypeAPI explicit and consistent with other generated assertions.Regression coverage
Typeassignability scenarios to ensure documentedtypeof(...)usage remains valid.