Testing Strategy
ManagedCode.Storage uses xUnit + Shouldly and aims to verify storage behaviour through realistic flows (upload/download/list/delete/metadata) with minimal mocking.
Test Project
Suite Map
flowchart TD
Tests[ManagedCode.Storage.Tests] --> Core[Core helpers + invariants]
Tests --> Providers[Provider suites]
Tests --> AspNet[ASP.NET controllers + SignalR]
Tests --> Vfs[VFS suites]
Providers --> Containers["Testcontainers (Azurite/LocalStack/FakeGcsServer/SFTP)"]
Providers --> CloudDrive["CloudDrive (Graph/Drive/Dropbox)"]
CloudDrive --> HttpFakes[HttpMessageHandler fakes wired into official SDK clients]
Structure
Tests are grouped by “surface” and provider:
Tests/ManagedCode.Storage.Tests/Core/—ManagedCode.Storage.Corebehaviour (helpers, options, invariants)Tests/ManagedCode.Storage.Tests/VirtualFileSystem/— VFS behaviour and fixturesTests/ManagedCode.Storage.Tests/Storages/*/— provider suites (Azure/AWS/GCS/Browser/FileSystem/Sftp/CloudDrive/CloudKit)Tests/ManagedCode.Storage.Tests/AspNetTests/— ASP.NET controllers + SignalR flows (end-to-end via in-process test host)Tests/ManagedCode.Storage.BrowserServerHost/— minimal interactive Blazor Server host used for real browser verification of IndexedDB metadata + OPFS payload flows over server-side JS interopTests/ManagedCode.Storage.BrowserWasmHost/— minimal standalone Blazor WebAssembly host used for real browser verification of browser storage flows with IndexedDB metadata and OPFS payloadsTests/ManagedCode.Storage.Tests/Common/— shared test utilities, Testcontainers helpers, test app host
External Dependencies
Where possible, tests run without real cloud accounts:
- Azure/AWS/GCS/SFTP suites use Testcontainers (Azurite, LocalStack, FakeGcsServer, SFTP container).
- The LocalStack-backed AWS and Orleans flows are pinned to
localstack/localstack:4.14.0because the end-of-March 2026latestimage became auth-gated and is no longer safe for anonymous CI runs. - Browser-local coverage uses Playwright against
Tests/ManagedCode.Storage.BrowserServerHost/andTests/ManagedCode.Storage.BrowserWasmHost/soManagedCode.Storage.Browseris exercised through real Chromium flows with IndexedDB metadata and OPFS payloads in both Interactive Server and standalone WASM modes. - Those same hosts also wire
ManagedCode.Storage.VirtualFileSystemover the browser provider, so browser VFS write, read, move, delete, large-file, small-file overwrite, and multi-tab concurrency flows are verified end to end in the browser rather than through in-process fakes. - The Interactive Server host explicitly raises
HubOptions.MaximumReceiveMessageSizeso browser-to-server chunk reads can exceed the default 32 KB SignalR limit during large-stream verification. - CloudDrive suites (OneDrive/Google Drive/Dropbox) use
HttpMessageHandler-based fakes wired into the official SDK clients, asserting real behaviour over HTTP without hitting the network.
Categories
Some tests are marked as “large file” to validate streaming behaviour:
[Trait("Category", "LargeFile")]- Browser-hosted stress flows also carry
[Trait("Category", "BrowserStress")].
Run the default fast suite:
dotnet test Tests/ManagedCode.Storage.Tests/ManagedCode.Storage.Tests.csproj --configuration Release --filter "Category!=BrowserStress"
Install the Playwright browser for the browser-local tests:
dotnet tool restore
dotnet build Tests/ManagedCode.Storage.Tests/ManagedCode.Storage.Tests.csproj --configuration Release
dotnet playwright -p Tests/ManagedCode.Storage.Tests/ManagedCode.Storage.Tests.csproj install chromium
Skip large-file tests when iterating:
dotnet test Tests/ManagedCode.Storage.Tests/ManagedCode.Storage.Tests.csproj --configuration Release --filter "Category!=LargeFile"
Skip the hosted-browser stress lane while still running the default fast browser coverage:
dotnet test Tests/ManagedCode.Storage.Tests/ManagedCode.Storage.Tests.csproj --configuration Release --filter "Category!=BrowserStress"
Run only the hosted-browser stress lane locally when you explicitly need it:
dotnet test Tests/ManagedCode.Storage.Tests/ManagedCode.Storage.Tests.csproj --configuration Release --filter "Category=BrowserStress"
Tiered browser large-file coverage now works like this:
- default
build-and-teststill includes a real end-to-end browser large-file lane, but at a fast128 MiBsize soStorage.GetStreamAsyncstays covered in the normal PR path Category=BrowserStressruns a heavier256 MiBcross-page integrity check for both Interactive Server and WASM, using a worker-side OPFS digest so the stress lane proves persistence without paying the old full.NETread-back cost- the
browser-stressCI job and theReleaseworkflow both run that explicit stress lane automatically
The earlier 1 GiB browser target was removed from automated CI because Chromium-backed WASM verification hit an unstable OPFS write boundary around 512 MiB, so 256 MiB became the stable automated stress target.
Quality Rules
- Each test must assert concrete, observable behaviour (state/output/errors/side-effects).
- Mocks/fakes are allowed only for external systems that cannot reasonably run in tests; the fake must match the official API surface (paths, status codes, payload shapes).
- Do not weaken or delete tests to make them pass; fix the behaviour instead.