Class SseStreamAndHttpAssertions
- Namespace
- SseAssertions.TUnit
- Assembly
- SseAssertions.TUnit.dll
Fluent TUnit entry points for asserting on Server-Sent Events streams produced by
Stream and HttpResponseMessage receivers: first-event,
in-order, retry-directive, content-type, and clean-cancellation checks. The frame-narrowing
HasSseEvent chain on these same receivers lives in
SseStreamHasEventAssertion and SseResponseHasEventAssertion; the
shared read and matching helpers (SseAssertions.TUnit.SseStreamReader, SseAssertions.TUnit.SseEventMatcher)
keep the diagnostics identical across all three receivers.
[SuppressMessage("Usage", "VSTHRD200:Use \"Async\" suffix for async methods", Justification = "These are [GenerateAssertion] source methods: the method name becomes the fluent chain entry point (Assert.That(response).HasSseEvent(...)), so an Async suffix would corrupt the assertion surface.")]
public static class SseStreamAndHttpAssertions
- Inheritance
-
SseStreamAndHttpAssertions
- Inherited Members
Remarks
Cancellation semantics: if the supplied CancellationToken fires during the body read, the partial buffer is parsed as best-effort SSE and the assertion runs against the partial event list. On chain pass, the assertion passes; on chain fail, the failure message renders the cancellation-cut-the-read variant (CancellationCutRead(int, int, string)).
On HttpResponseMessage, strictContentType defaults to
true: a response without Content-Type: text/event-stream fails with
the UnexpectedContentType(string?) diagnostic. Pass
false for test mocks that serve SSE without the canonical header.
Methods
EndsCleanlyOnCancellation(Stream, CancellationToken)
Asserts the supplied Stream tears down cleanly when its read is cancelled: the read either completes normally or surfaces cooperative cancellation (OperationCanceledException), but not a transport exception (IOException, HttpRequestException). Pass a token that fires mid-stream; the assertion drains and discards content, checking only teardown behaviour.
[GenerateAssertion]
public static Task<AssertionResult> EndsCleanlyOnCancellation(this Stream stream, CancellationToken cancellationToken = default)
Parameters
streamStreamThe SSE stream whose cancellation teardown to verify.
cancellationTokenCancellationTokenThe token expected to cancel the read mid-stream.
Returns
- Task<AssertionResult>
A passing assertion when the read ends cleanly; otherwise a failing assertion naming the transport exception that surfaced.
Exceptions
- ArgumentNullException
streamis null.
EndsCleanlyOnCancellation(HttpResponseMessage, bool, CancellationToken)
Asserts the supplied HttpResponseMessage body tears down cleanly when its read is cancelled: the read either completes normally or surfaces cooperative cancellation (OperationCanceledException), but not a transport exception (IOException, HttpRequestException). Pass a token that fires mid-stream; the assertion drains and discards content, checking only teardown behaviour.
[GenerateAssertion]
public static Task<AssertionResult> EndsCleanlyOnCancellation(this HttpResponseMessage response, bool strictContentType = true, CancellationToken cancellationToken = default)
Parameters
responseHttpResponseMessageThe HTTP response carrying the SSE body whose cancellation teardown to verify.
strictContentTypeboolWhen true (the default), the assertion fails if
Content-Type's media type is nottext/event-stream. Set to false for test mocks that serve SSE without the canonical header.cancellationTokenCancellationTokenThe token expected to cancel the read mid-stream.
Returns
- Task<AssertionResult>
A passing assertion when the read ends cleanly; otherwise a failing assertion naming the transport exception that surfaced, or the unexpected-content-type diagnostic when
strictContentTypeis on and the header is wrong.
Exceptions
- ArgumentNullException
responseis null.
HasFirstSseEvent(Stream, string, CancellationToken)
Asserts the first SSE frame in stream has event:
equal to eventName. Unlabelled frames match
HasFirstSseEvent("message") per the WHATWG default-event-name rule. The full
stream is read before parsing; cancellationToken bounds the read.
[GenerateAssertion]
public static Task<AssertionResult> HasFirstSseEvent(this Stream stream, string eventName, CancellationToken cancellationToken = default)
Parameters
streamStreamThe SSE stream.
eventNamestringThe event-type name expected on the first frame.
cancellationTokenCancellationTokenFlows to the stream read.
Returns
- Task<AssertionResult>
A passing assertion when the first parsed frame matches; otherwise a failing assertion describing the first event observed, "no events", or the cancellation diagnostic if the read was cut before any frame completed.
Exceptions
- ArgumentNullException
streamoreventNameis null.
HasFirstSseEvent(HttpResponseMessage, string, bool, CancellationToken)
Asserts the first SSE frame in response's body has
event: equal to eventName. Unlabelled frames match
HasFirstSseEvent("message") per the WHATWG default-event-name rule. Body is read
in full before parsing; cancellationToken bounds the read.
[GenerateAssertion]
public static Task<AssertionResult> HasFirstSseEvent(this HttpResponseMessage response, string eventName, bool strictContentType = true, CancellationToken cancellationToken = default)
Parameters
responseHttpResponseMessageThe HTTP response carrying the SSE body.
eventNamestringThe event-type name expected on the first frame.
strictContentTypeboolWhen true (the default), the assertion fails if
Content-Type's media type is nottext/event-stream. Set to false for test mocks that serve SSE without the canonical header.cancellationTokenCancellationTokenFlows to the response-body read.
Returns
- Task<AssertionResult>
A passing assertion when the first parsed frame matches; otherwise a failing assertion describing the first event observed, "no events", the unexpected content-type diagnostic (when
strictContentTypeis on), or the cancellation diagnostic if the read was cut before any frame completed.
Exceptions
- ArgumentNullException
responseoreventNameis null.
HasSseContentType(HttpResponseMessage, bool)
Asserts the supplied HttpResponseMessage's Content-Type
header indicates a Server-Sent Events stream. Header-only check; the response body is
not read. Use this as a lightweight smoke-test discriminator for SSE endpoints.
[GenerateAssertion]
public static AssertionResult HasSseContentType(this HttpResponseMessage response, bool strict = false)
Parameters
responseHttpResponseMessageThe HTTP response whose
Content-Typeto inspect.strictboolWhen false (the default), passes when the media type is
text/event-stream(case-insensitive); trailing parameters like; charset=utf-8are ignored. When true, requires the fullContent-Typeheader to be exactlytext/event-streamwith no parameters.
Returns
- AssertionResult
An assertion that passes when the
Content-Typematches perstrict.
Exceptions
- ArgumentNullException
responseis null.
HasSseEventsInOrder(Stream, IReadOnlyList<string>, bool, CancellationToken)
Asserts the supplied Stream contains the named SSE events in order.
When strictOrdering is false (default), other events
may appear between the named ones; when true, the named events must
appear contiguously.
[GenerateAssertion]
public static Task<AssertionResult> HasSseEventsInOrder(this Stream stream, IReadOnlyList<string> eventNames, bool strictOrdering = false, CancellationToken cancellationToken = default)
Parameters
streamStreamThe SSE stream.
eventNamesIReadOnlyList<string>The event-type names expected in order. An empty array trivially passes.
strictOrderingboolPass true to require the named events to appear contiguously with no other events between them.
cancellationTokenCancellationTokenFlows to the stream read.
Returns
- Task<AssertionResult>
An assertion that passes when the order constraint is satisfied; otherwise a failing assertion describing the first violation.
Exceptions
- ArgumentNullException
streamoreventNamesis null.
HasSseEventsInOrder(HttpResponseMessage, IReadOnlyList<string>, bool, bool, CancellationToken)
Asserts the supplied HttpResponseMessage body contains the named
SSE events in order. When strictOrdering is false
(default), other events may appear between the named ones; when true,
the named events must appear contiguously.
[GenerateAssertion]
public static Task<AssertionResult> HasSseEventsInOrder(this HttpResponseMessage response, IReadOnlyList<string> eventNames, bool strictOrdering = false, bool strictContentType = true, CancellationToken cancellationToken = default)
Parameters
responseHttpResponseMessageThe HTTP response carrying the SSE body.
eventNamesIReadOnlyList<string>The event-type names expected in order. An empty array trivially passes.
strictOrderingboolPass true to require the named events to appear contiguously with no other events between them.
strictContentTypeboolWhen true (the default), the assertion fails if
Content-Type's media type is nottext/event-stream.cancellationTokenCancellationTokenFlows to the response-body read.
Returns
- Task<AssertionResult>
An assertion that passes when the order constraint is satisfied; otherwise a failing assertion describing the violation or the unexpected content-type.
Exceptions
- ArgumentNullException
responseoreventNamesis null.
HasSseRetryDirective(Stream, int?, CancellationToken)
Asserts the supplied Stream contains a retry: directive.
When millis is supplied, requires at least one frame whose
retry: value equals it; when null, any retry value passes.
[GenerateAssertion]
public static Task<AssertionResult> HasSseRetryDirective(this Stream stream, int? millis = null, CancellationToken cancellationToken = default)
Parameters
streamStreamThe SSE stream.
millisint?The required
retry:value in milliseconds, or null to accept any value.cancellationTokenCancellationTokenFlows to the stream read.
Returns
- Task<AssertionResult>
An assertion that passes when a matching
retry:directive is found.
Exceptions
- ArgumentNullException
streamis null.
HasSseRetryDirective(HttpResponseMessage, int?, bool, CancellationToken)
Asserts the supplied HttpResponseMessage body contains a
retry: directive. When millis is supplied, requires at least one
frame whose retry: value equals it; when null, any retry value
passes.
[GenerateAssertion]
public static Task<AssertionResult> HasSseRetryDirective(this HttpResponseMessage response, int? millis = null, bool strictContentType = true, CancellationToken cancellationToken = default)
Parameters
responseHttpResponseMessageThe HTTP response carrying the SSE body.
millisint?The required
retry:value in milliseconds, or null to accept any value.strictContentTypeboolWhen true (the default), the assertion fails if
Content-Type's media type is nottext/event-stream.cancellationTokenCancellationTokenFlows to the response-body read.
Returns
- Task<AssertionResult>
An assertion that passes when a matching
retry:directive is found, or fails with the unexpected-content-type diagnostic whenstrictContentTypeis on and the header is wrong.
Exceptions
- ArgumentNullException
responseis null.
HasSseRetryDirectiveFirst(Stream, int, CancellationToken)
Asserts the supplied Stream sends a retry: directive before any
data-bearing event and that the leading directive's value equals
millis: position and value pinned in a single read.
[GenerateAssertion]
public static Task<AssertionResult> HasSseRetryDirectiveFirst(this Stream stream, int millis, CancellationToken cancellationToken = default)
Parameters
streamStreamThe SSE stream.
millisintThe required
retry:value, in milliseconds, of the leading directive.cancellationTokenCancellationTokenFlows to the stream read.
Returns
- Task<AssertionResult>
An assertion that passes when a
retry: millisdirective precedes the first data event.
Exceptions
- ArgumentNullException
streamis null.
HasSseRetryDirectiveFirst(Stream, CancellationToken)
Asserts the supplied Stream sends a retry: directive before
any data-bearing event: the server set the reconnection time before streaming any payload.
[GenerateAssertion]
public static Task<AssertionResult> HasSseRetryDirectiveFirst(this Stream stream, CancellationToken cancellationToken = default)
Parameters
streamStreamThe SSE stream.
cancellationTokenCancellationTokenFlows to the stream read.
Returns
- Task<AssertionResult>
An assertion that passes when a
retry:directive precedes the first data event.
Exceptions
- ArgumentNullException
streamis null.
HasSseRetryDirectiveFirst(HttpResponseMessage, bool, CancellationToken)
Asserts the supplied HttpResponseMessage body sends a retry:
directive before any data-bearing event.
[GenerateAssertion]
public static Task<AssertionResult> HasSseRetryDirectiveFirst(this HttpResponseMessage response, bool strictContentType = true, CancellationToken cancellationToken = default)
Parameters
responseHttpResponseMessageThe HTTP response carrying the SSE body.
strictContentTypeboolWhen true (the default), the assertion fails if
Content-Type's media type is nottext/event-stream.cancellationTokenCancellationTokenFlows to the response-body read.
Returns
- Task<AssertionResult>
An assertion that passes when a
retry:directive precedes the first data event, or fails with the unexpected-content-type diagnostic whenstrictContentTypeis on and the header is wrong.
Exceptions
- ArgumentNullException
responseis null.
HasSseRetryDirectiveFirst(HttpResponseMessage, int, bool, CancellationToken)
Asserts the supplied HttpResponseMessage body sends a retry:
directive before any data-bearing event and that the leading directive's value equals
millis: position and value pinned in a single read of the forward-only
response body, which a separate position assertion and value assertion cannot both inspect.
[GenerateAssertion]
public static Task<AssertionResult> HasSseRetryDirectiveFirst(this HttpResponseMessage response, int millis, bool strictContentType = true, CancellationToken cancellationToken = default)
Parameters
responseHttpResponseMessageThe HTTP response carrying the SSE body.
millisintThe required
retry:value, in milliseconds, of the leading directive.strictContentTypeboolWhen true (the default), the assertion fails if
Content-Type's media type is nottext/event-stream.cancellationTokenCancellationTokenFlows to the response-body read.
Returns
- Task<AssertionResult>
An assertion that passes when a
retry: millisdirective precedes the first data event, or fails with the unexpected-content-type diagnostic whenstrictContentTypeis on and the header is wrong.
Exceptions
- ArgumentNullException
responseis null.