Getting started
Requirements
The packages target .NET Standard 2.0 and 2.1, .NET 6, .NET 8, .NET 9 and .NET 10, so they also work in .NET Framework projects. Some members are only available on newer target frameworks; the pages that describe them say so.
Install the packages
Install Testably.Abstractions in your production projects:
- .NET CLI
- PackageReference
- Central Package Management
dotnet add package Testably.Abstractions
<PackageReference Include="Testably.Abstractions" Version="10.4.0" />
<PackageVersion Include="Testably.Abstractions" Version="10.4.0" />
<PackageReference Include="Testably.Abstractions" />
Latest version: 10.4.0
and Testably.Abstractions.Testing in your test projects:
- .NET CLI
- PackageReference
- Central Package Management
dotnet add package Testably.Abstractions.Testing
<PackageReference Include="Testably.Abstractions.Testing" Version="7.2.0" />
<PackageVersion Include="Testably.Abstractions.Testing" Version="7.2.0" />
<PackageReference Include="Testably.Abstractions.Testing" />
Latest version: 7.2.0
| Package | Install it in |
|---|---|
Testably.Abstractions | Production code: contains RealFileSystem, RealTimeSystem and RealRandomSystem |
Testably.Abstractions.Testing | Test projects: contains MockFileSystem, MockTimeSystem and MockRandomSystem |
Testably.Abstractions.Interface | Libraries that only consume IFileSystem, ITimeSystem or IRandomSystem and leave the choice of implementation to the application |
Testably.Abstractions.FileSystem.Interface | Libraries that only need IFileSystem |
Both Testably.Abstractions and Testably.Abstractions.Testing pull in the interface packages transitively.
Optional companion packages add compression, access control and memory-mapped files; each page shows how to install it.
Register the abstractions
With Microsoft.Extensions.DependencyInjection:
builder.Services
.AddSingleton<IFileSystem, RealFileSystem>()
.AddSingleton<IRandomSystem, RealRandomSystem>()
.AddSingleton<ITimeSystem, RealTimeSystem>();
Use the interfaces in your services
public class CatalogService(IFileSystem fileSystem)
{
public void Export(string json)
{
fileSystem.Directory.CreateDirectory("exports");
fileSystem.File.WriteAllText("exports/catalog.json", json);
}
}
Write your first test
In the test, replace the real implementation with the mock:
using Testably.Abstractions.Testing;
using static aweXpect.Expect;
public class CatalogServiceTests
{
[Test]
public async Task Export_ShouldWriteCatalogToExportsFolder()
{
MockFileSystem fileSystem = new();
CatalogService sut = new(fileSystem);
sut.Export("""{ "title": "Red Square" }""");
await That(fileSystem.File.ReadAllText("exports/catalog.json"))
.IsEqualTo("""{ "title": "Red Square" }""");
}
}
That's it: your code now runs against an in-memory file system in tests, and against the real one in production.
Next steps
- A complete example: one gallery service tested with the file system, time and random system together.
- File system:
IFileSystem,MockFileSystem, drives, watcher, statistics, strategies. - Time system:
ITimeSystem, time providers, timers, auto-advance, notifications. - Random system:
IRandomSystemand deterministic generators. - Companion libraries: Compression, AccessControl and MemoryMappedFiles.
- aweXpect.Testably: expectations for the file system and time system mocks, if you use aweXpect.