Asynchronous values
editSnapshot.Validate reads its value synchronously. A Stream that only supports asynchronous reads makes it fail, and an IAsyncEnumerable<T> is enumerated by blocking the test until every item is produced. Snapshot.ValidateAsync reads both asynchronously and accepts a CancellationToken. It takes the same type and settings as Snapshot.Validate, and the snapshot gets the same name.
Validate a stream
The stream is read with CopyToAsync and stored as its bytes:
await using var stream = new MemoryStream("Hello, world!"u8.ToArray());
// The stream is read with CopyToAsync, from its current position, and is neither rewound nor disposed
await Snapshot.ValidateAsync(stream, TestContext.Current.CancellationToken); // __snapshots__/SnapshotTests_DocumentationExample_ValidateAsync.verified.txt- The stream is read from its current position to its end. It is neither rewound nor disposed: a stream you have just written to must be rewound first, or the snapshot is empty.
- Once read, the content is validated like a
Streampassed to Snapshot.Validate, so a serializer registered for streams still applies.
Validate an asynchronous sequence
The sequence is enumerated with await foreach, and the items are written like a list:
static async IAsyncEnumerable<string> GetNamesAsync()
{
foreach (var name in new[] { "John", "Jane" })
{
await Task.Yield(); // For instance, a page of results from a database or a web API
yield return name;
}
}
// The sequence is enumerated with await foreach instead of blocking the test
await Snapshot.ValidateAsync(GetNamesAsync(), TestContext.Current.CancellationToken); // __snapshots__/SnapshotTests_DocumentationExample_ValidateAsyncEnumerable.verified.txt- The snapshot is the same as the one Snapshot.Validate writes for the sequence, including for a sequence of
KeyValuePair<string, T>, which is written like a dictionary. - The serializers receive the items as a
List<T>, so a serializer registered forIAsyncEnumerable<T>does not apply. - Only the value you pass is enumerated asynchronously. An
IAsyncEnumerable<T>in a property of an object is still enumerated by blocking.
Completion and cancellation
- The value is read into memory before anything else happens. No snapshot file is read or written before the stream is fully read or the sequence fully enumerated.
- The task completes after the comparison and the update of the snapshot files, and fails with the same exception as Snapshot.Validate when the snapshot differs.
- Canceling the token while the value is read throws an
OperationCanceledExceptionand leaves the snapshot files untouched.