This library is a feature complete testing helper for the IFileSystem abstractions for I/O-related functionality from the System.IO namespace. It uses an in-memory file system that behaves exactly like the real file system and can be used in unit tests for dependency injection.
The testing helper also supports advanced scenarios like
- Multiple drives with limited size
FileSystemWatcherand- a way to work with SafeFileHandles
The companion projects Testably.Abstractions.Compression and Testably.Abstractions.AccessControl allow working with Zip-Files and Access Control Lists respectively.
As the test suite runs both against the mocked and the real file system, the behaviour between the two is identical.
In addition, the following interfaces are defined:
- The
ITimeSysteminterface abstracts away time-related functionality:DateTimemethods give access to the current timeTaskallows replacingTask.DelayThreadallows replacingThread.SleepTimeris a wrapper aroundSystem.Threading.Timer
- The
IRandomSysteminterface abstracts away functionality related to randomness:
Randommethods implement a thread-safe Shared instance also under .NET Framework andGuidmethods allow creating new GUIDs.
Example
Use the interfaces and their default implementations using your prefered dependency injection method, e.g.:
private readonly IFileSystem _fileSystem;
public class MyService(IFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
public void StoreData()
{
var fileContent = GetFileContent();
_fileSystem.File.WriteAllText("result.xml", fileContent);
}
private string GetFileContent()
{
// Generate the file content
}Then you test your class with the mocked types in Testably.Abstractions.Testing:
[Fact]
public void StoreData_ShouldWriteValidFile()
{
IFileSystem fileSystem = new MockFileSystem();
MyService sut = new MyService(fileSystem);
sut.StoreData();
var fileContent = fileSystem.File.ReadAllText("result.xml");
// Validate fileContent
}More examples can be found in the examples section!
Getting Started
-
Install
Testably.Abstractionsas nuget package in your productive projects andTestably.Abstractions.Testingas nuget package in your test projects.dotnet add package Testably.Abstractions dotnet add package Testably.Abstractions.Testing
-
Configure your dependeny injection framework, e.g. with
Microsoft.Extensions.DependencyInjectionsin ASP.NET core:builder.Services .AddSingleton<IFileSystem, RealFileSystem>() .AddSingleton<IRandomSystem, RealRandomSystem>() .AddSingleton<ITimeSystem, RealTimeSystem>();
You can now use the interfaces in your services!
Testing
In order to simplify testing, the Testably.Abstractions.Testing project provides mocked instances for the abstraction interfaces:
These mocks are configured using fluent syntax:
new MockFileSystem()
.WithDrive("D:", d => d
.SetTotalSize(1024 * 1024))
.InitializeIn("D:")
.WithFile("foo.txt")
.WithSubdirectory("sub-dir").Initialized(s => s
.WithAFile(".json").Which(
f => f.HasStringContent("{\"count\":1}")));Initializes the mocked file system with a second drive D: with 1MB total available space and creates on it an empty text file foo.txt and a directory sub-dir which contains randomly named json file with {"count":1} as file content.
