GrpcAssertions.TUnit
0.1.0
dotnet add package GrpcAssertions.TUnit --version 0.1.0
NuGet\Install-Package GrpcAssertions.TUnit -Version 0.1.0
<PackageReference Include="GrpcAssertions.TUnit" Version="0.1.0" />
<PackageVersion Include="GrpcAssertions.TUnit" Version="0.1.0" />
<PackageReference Include="GrpcAssertions.TUnit" />
paket add GrpcAssertions.TUnit --version 0.1.0
#r "nuget: GrpcAssertions.TUnit, 0.1.0"
#:package GrpcAssertions.TUnit@0.1.0
#addin nuget:?package=GrpcAssertions.TUnit&version=0.1.0
#tool nuget:?package=GrpcAssertions.TUnit&version=0.1.0
GrpcAssertions.TUnit
Scope: Test projects only. Not intended for production code.
TUnit-native gRPC assertions for .NET tests. Fluent entry points over TUnit's Assert.That(...) pipeline for asserting on gRPC call outcomes. AOT-compatible, trimmable, no runtime reflection in the assertion path.
What ships
Delegate assertions on Assert.That(() => client.Method(...)):
| Entry point | Behaviour |
|---|---|
ThrowsGrpcException() / ThrowsGrpcException(StatusCode) |
Asserts the call throws an RpcException (optionally with a status). Returns a chain. |
DoesNotThrowGrpcException() |
Asserts the call completes without throwing an RpcException. |
IsRpcException() (on a caught Exception) |
Asserts the exception is a gRPC RpcException. |
Chain off ThrowsGrpcException(): 14 StatusCode shorthands (IsUnavailable(), IsNotFound(), and the rest), plus WithDetail(string) and WithDetailContaining(string, StringComparison).
The framework-agnostic core (GrpcAssertions) also ships the GrpcCallBuilder test-double helper for building AsyncUnaryCall<T> fakes.
Install
dotnet add package GrpcAssertions.TUnit
Requirements: TUnit 1.48.6 or later, .NET 10. The framework-agnostic GrpcAssertions core and its Grpc.Core.Api dependency come transitively.
Quick start
await Assert.That(() => client.PredictAsync(request, ct))
.ThrowsGrpcException(StatusCode.Unavailable)
.WithDetailContaining("connection refused", StringComparison.Ordinal);
await Assert.That(() => client.ClosePickCycleAsync(request, ct))
.DoesNotThrowGrpcException();
The full reference, including the GrpcCallBuilder test doubles and the complete shorthand list, is in the GitHub README.
License
MIT. Depends transitively on Grpc.Core.Api (Apache-2.0).
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Grpc.Core.Api (>= 2.80.0)
- GrpcAssertions (>= 0.1.0)
- TUnit.Assertions (>= 1.47.0)
- TUnit.Core (>= 1.47.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
View the rendered release notes: https://github.com/JohnVerheij/GrpcAssertions.TUnit/releases/tag/v0.1.0
Feature release. Lifts the package from skeleton to functional: the gRPC outcome-assertion surface ships. `ThrowsGrpcException()` asserts a delegate threw an `RpcException`, with `StatusCode` shorthands and `Status.Detail` refinements; `DoesNotThrowGrpcException()` covers the benign-error swallow tests; and `GrpcCallBuilder` removes the five-parameter `AsyncUnaryCall<T>` constructor that every hand-rolled gRPC fake repeats. The v0.0.1 `IsRpcException()` discriminator is preserved unchanged.
### Added
- **`Assert.That(() => call).ThrowsGrpcException()`** asserts the delegate throws a gRPC `RpcException` of any status; **`ThrowsGrpcException(StatusCode expected)`** asserts the status. Both return a `GrpcExceptionAssertion` chain, and failure messages render the actual `StatusCode` and `Status.Detail`. The entry points extend the delegate assertion source produced by `Assert.That(() => client.Method(...))`.
- **14 `StatusCode` shorthands** chaining off `ThrowsGrpcException()`: `IsOk`, `IsCancelled`, `IsInvalidArgument`, `IsDeadlineExceeded`, `IsNotFound`, `IsAlreadyExists`, `IsPermissionDenied`, `IsResourceExhausted`, `IsFailedPrecondition`, `IsAborted`, `IsUnimplemented`, `IsInternal`, `IsUnavailable`, `IsUnauthenticated`.
- **`WithDetail(string)`** (exact, ordinal) and **`WithDetailContaining(string, StringComparison)`** (substring, explicit comparison per the family convention) refine the assertion on `Status.Detail`.
- **`Assert.That(() => call).DoesNotThrowGrpcException()`** asserts the delegate completes without throwing an `RpcException`. A thrown `RpcException` fails with the gRPC outcome rendered; any other thrown exception fails naming its type and message.
- **`GrpcCallBuilder`** (core `GrpcAssertions` package): `Success<T>(T)`, `Faulted<T>(RpcException)`, and `Faulted<T>(StatusCode, string?)` build `AsyncUnaryCall<T>` instances for gRPC client test doubles, replacing the repeated five-parameter constructor. Both builders guard their arguments with `ArgumentNullException.ThrowIfNull`, a strict improvement over the hand-rolled fakes that would dereference-null later.
- **`GrpcOutcomeRendering`** (core): `Describe(RpcException)` and `DescribeStatus(StatusCode, string?)` render the status and detail (truncated at `MaxDetailLength`, 200 characters, with a horizontal-ellipsis suffix) for failure messages, shared so consumer-authored gRPC assertions produce identical diagnostics.
### Changed
- Pinned `PackageValidationBaselineVersion` to `0.0.1` on both packages; ApiCompat strict-mode now validates v0.1.0 against the v0.0.1 baseline at pack time. The v0.1.0 additions are purely additive (no breaking changes); strict-mode records the new public types as additive baseline suppressions (`CP0001`) in `CompatibilitySuppressions.xml`.
- Exempted `VSTHRD003` in test projects (`.editorconfig`). Tests routinely await Tasks created elsewhere (for example `AsyncUnaryCall<T>.ResponseAsync` from `GrpcCallBuilder`), which is safe under the no-`SynchronizationContext` test runner; the analyzer guards against a UI-thread deadlock that cannot occur here.