aweXpect.Testably 0.15.0

Prefix Reserved
dotnet add package aweXpect.Testably --version 0.15.0
                    
NuGet\Install-Package aweXpect.Testably -Version 0.15.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="aweXpect.Testably" Version="0.15.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="aweXpect.Testably" Version="0.15.0" />
                    
Directory.Packages.props
<PackageReference Include="aweXpect.Testably" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add aweXpect.Testably --version 0.15.0
                    
#r "nuget: aweXpect.Testably, 0.15.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package aweXpect.Testably@0.15.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=aweXpect.Testably&version=0.15.0
                    
Install as a Cake Addin
#tool nuget:?package=aweXpect.Testably&version=0.15.0
                    
Install as a Cake Tool

aweXpect.Testably

Changelog

Nuget Coverage Mutation testing badge

Expectations for the file and time system from Testably.Abstractions.

File system

You can verify that a specific file or directory exists in the file system:

IFileSystem fileSystem = new MockFileSystem();
fileSystem.Directory.CreateDirectory("my/path");
fileSystem.File.WriteAllText("my-file.txt", "some content");

await That(fileSystem).HasDirectory("my/path");
await That(fileSystem).HasFile("my-file.txt");

File

For files, you can verify the file content:

IFileSystem fileSystem = new MockFileSystem();
fileSystem.File.WriteAllText("my-file.txt", "some content");

await That(fileSystem).HasFile("my-file.txt").WithContent("some content").IgnoringCase();
await That(fileSystem).HasFile("my-file.txt").WithContent().NotEqualTo("some unexpected content");

You can also verify the file content with regard to another file:

IFileSystem fileSystem = new MockFileSystem();
fileSystem.File.WriteAllText("my-file.txt", "some content");
fileSystem.File.WriteAllText("my-other-file.txt", "SOME CONTENT");
fileSystem.File.WriteAllText("my-third-file.txt", "some other content");

await That(fileSystem).HasFile("my-file.txt").WithContent().SameAs("my-other-file.txt").IgnoringCase();
await That(fileSystem).HasFile("my-file.txt").WithContent().NotSameAs("my-third-file.txt");

For files, you can verify the creation time, last access time and last write time:

IFileSystem fileSystem = new MockFileSystem();
fileSystem.File.WriteAllText("my-file.txt", "some content");

await That(sut).HasFile(path).WithCreationTime(DateTime.Now).Within(1.Second());
await That(sut).HasFile(path).WithLastAccessTime(DateTime.Now).Within(1.Second());
await That(sut).HasFile(path).LastWriteTime(DateTime.Now).Within(1.Second());

Directory

For directories, you can verify that they contain subdirectories:

IFileSystem fileSystem = new MockFileSystem();
fileSystem.Directory.CreateDirectory("foo/bar1");
fileSystem.Directory.CreateDirectory("foo/bar2/baz");

await That(fileSystem).HasDirectory("foo").WithDirectories(f => f.HasCount().EqualTo(2));

For directories, you can verify that they contain files:

IFileSystem fileSystem = new MockFileSystem();
fileSystem.Directory.CreateDirectory("foo/bar");
fileSystem.File.WriteAllText("foo/bar/my-file.txt", "some content");

await That(fileSystem).HasDirectory("foo/bar").WithFiles(f => f.All().ComplyWith(x => x.HasContent("SOME CONTENT").IgnoringCase()));

Drives

You can verify that a drive is registered on the file system. Drives are matched by name (case-insensitive) against IFileSystem.DriveInfo.GetDrives(); UNC drives (which do not appear in GetDrives()) are not supported by HasDrive:

MockFileSystem fileSystem = new(o => o.SimulatingOperatingSystem(SimulationMode.Windows));
fileSystem.WithDrive("D:", d => d.SetTotalSize(2048));

await That(fileSystem).HasDrive("D:\\");
await That(fileSystem).DoesNotHaveDrive("Z:\\");

HasDrive exposes a .Which property returning IThat<IDriveInfo>, so all IDriveInfo assertions can be chained directly:

await That(fileSystem).HasDrive("D:\\")
    .Which.HasTotalSize(2048).And.IsReady();

You can also assert directly on IDriveInfo instances:

IDriveInfo driveInfo = fileSystem.DriveInfo.New("D:");

await That(driveInfo).HasAvailableFreeSpace(2048);
await That(driveInfo).HasTotalSize(2048).And.HasTotalFreeSpace(2048);
await That(driveInfo).HasDriveFormat("NTFS");
await That(driveInfo).HasDriveType(System.IO.DriveType.Fixed);
await That(driveInfo).HasName(driveInfo.Name).And.HasVolumeLabel(driveInfo.VolumeLabel);
await That(driveInfo).IsReady();

IFileInfo / IDirectoryInfo as subjects

You can also assert directly on IFileInfo and IDirectoryInfo instances:

IFileInfo fileInfo = fileSystem.FileInfo.New("my-file.txt");
await That(fileInfo).HasLength(12).And.HasContent("some content");
await That(fileInfo).HasName("my-file.txt").And.HasExtension(".txt");
await That(fileInfo).Exists();

IDirectoryInfo dirInfo = fileSystem.DirectoryInfo.New("foo");
await That(dirInfo).IsNotEmpty();
await That(dirInfo).HasFile("bar/my-file.txt");
await That(dirInfo).HasDirectory("bar").Which.HasFile("my-file.txt");

Bridging from the file-system chain via .Which

HasFile, HasDirectory and HasDrive expose a .Which property that returns the IThat<IFileInfo> / IThat<IDirectoryInfo> / IThat<IDriveInfo> for the resolved entry, so the same assertions light up in both places:

await That(fileSystem).HasFile("my-file.txt").Which.HasLength(12).And.HasContent("some content");
await That(fileSystem).HasDirectory("logs").Which.IsEmpty();
await That(fileSystem).HasDrive("D:\\").Which.IsReady().And.HasDriveFormat("NTFS");

IFileVersionInfo

IFileVersionInfo instances obtained via MockFileSystem.FileVersionInfo.GetVersionInfo can be asserted directly. The configured values come from MockFileSystem.WithFileVersionInfo(glob, builder):

MockFileSystem fileSystem = new();
fileSystem.WithFileVersionInfo("*.dll", v => v
    .SetCompanyName("Acme")
    .SetProductName("Anvil")
    .SetFileVersion("1.2.3.4")
    .SetIsDebug(true));
fileSystem.File.WriteAllText("Acme.dll", "");

IFileVersionInfo info = fileSystem.FileVersionInfo.GetVersionInfo("Acme.dll");

await That(info).HasCompanyName("Acme").And.HasProductName("Anvil");
await That(info).HasFileVersion("1.2.3.4");
await That(info).IsDebug().And.IsNotPreRelease();

The following common fields have dedicated assertions: HasCompanyName, HasProductName, HasFileDescription, HasFileVersion, HasProductVersion, HasOriginalFilename, HasLanguage, plus the bool pairs IsDebug / IsNotDebug, IsPreRelease / IsNotPreRelease, IsPatched / IsNotPatched. For the remaining properties (e.g. Comments, LegalCopyright, FileMajorPart), assert on them directly via await That(info.LegalCopyright).IsEqualTo("…").

Notifications

A MockFileSystem raises notifications when files or directories change. Run the code under test, then assert against the notifications it produced:

MockFileSystem fileSystem = new();
fileSystem.File.WriteAllText("my-file.txt", "some content");

await That(fileSystem).TriggeredNotification();
await That(fileSystem).TriggeredNotification(c => c.Name == "my-file.txt");

.Within(timeout) (default 30 s) lets the assertion wait for asynchronous notifications — if a matching notification already fired the assertion completes synchronously, otherwise it waits up to the timeout for a late arrival:

_ = Task.Run(() => fileSystem.File.WriteAllText("foo.txt", "x"));
await That(fileSystem).TriggeredNotification().Within(100.Milliseconds());

DidNotTriggerNotification mirrors the same shapes and short-circuits as soon as a matching notification is observed:

await That(fileSystem).DidNotTriggerNotification().Within(100.Milliseconds());
await That(fileSystem).DidNotTriggerNotification(c => c.Name == "secret.txt");

TriggeredNotification accepts a Quantifier (AtLeast, AtMost, Exactly, Between, Never, Once) so you can assert how often the notification fires:

fileSystem.File.WriteAllText("a.txt", "x");
fileSystem.File.WriteAllText("b.txt", "y");

await That(fileSystem).TriggeredNotification(c => c.ChangeType == WatcherChangeTypes.Created)
    .Exactly(2.Times());

Both TriggeredNotification and DidNotTriggerNotification expose .Which(c => …), which applies inner expectations from ChangeDescriptionExtensions as an additional per-notification filter — only changes that satisfy them count:

fileSystem.File.WriteAllText("a.txt", "x");

await That(fileSystem)
    .TriggeredNotification()
    .Which(c => c.HasName("a.txt").And.HasChangeType(WatcherChangeTypes.Created))
    .Exactly(1.Times());

Replay of historical notifications relies on the MockFileSystem notification history. Disable it via new MockFileSystem(o => o.WithoutNotificationHistory()) only if you don't use these assertions — they throw against a history-disabled file system.

Watcher events

An individual IFileSystemWatcher can also be the subject. The watcher must come from a MockFileSystem, and EnableRaisingEvents must be true for any event to be observed:

MockFileSystem fileSystem = new();
using IFileSystemWatcher watcher = fileSystem.FileSystemWatcher.New("/");
watcher.EnableRaisingEvents = true;
fileSystem.File.WriteAllText("my-file.txt", "some content");

await That(watcher).Triggered();
await That(watcher).Triggered(c => c.Name == "my-file.txt");

Only events that originate from this specific watcher count — events fired on other watchers of the same MockFileSystem are ignored.

.Within(timeout) (default 30 s) lets the assertion wait for asynchronous events:

_ = Task.Run(() => fileSystem.File.WriteAllText("foo.txt", "x"));
await That(watcher).Triggered().Within(100.Milliseconds());

DidNotTrigger mirrors the same shapes and short-circuits as soon as a matching event is observed:

await That(watcher).DidNotTrigger().Within(100.Milliseconds());
await That(watcher).DidNotTrigger(c => c.Name == "secret.txt");

Both Triggered and DidNotTrigger accept either a synchronous Func<WatcherChangeDescription, bool> predicate or a .Which(c => …) callback that composes inner expectations from ChangeDescriptionExtensions:

await That(watcher)
    .Triggered()
    .Which(c => c.HasName("my-file.txt").And.HasChangeType(WatcherChangeTypes.Created))
    .Exactly(1.Times());

ChangeDescription as a subject

Individual ChangeDescription instances can be asserted directly. The HasChangeType, HasFileSystemType and HasNotifyFilters assertions use flag containment (so a LastWrite | FileName change satisfies HasNotifyFilters(NotifyFilters.LastWrite)); the empty / default value is rejected with an ArgumentException to avoid silent passes.

await That(change).HasChangeType(WatcherChangeTypes.Created);
await That(change).DoesNotHaveChangeType(WatcherChangeTypes.Deleted);

await That(change).HasFileSystemType(FileSystemTypes.File);
await That(change).HasNotifyFilters(NotifyFilters.LastWrite);

await That(change).HasName("my-file.txt").And.HasPath("/abs/my-file.txt");
await That(renamedChange).HasOldName("old.txt").And.HasOldPath("/abs/old.txt");

Time system

Timers

A MockTimeSystem exposes timers as ITimerMock. You can assert how often the timer callback was executed without blocking the test thread:

MockTimeSystem timeSystem = new();
ITimerMock timer = (ITimerMock)timeSystem.Timer.New(
    _ => { }, null, TimeSpan.Zero, TimeSpan.FromMilliseconds(10));

await That(timer).Executed(3.Times()).Within(5.Seconds());

Executed() accepts a Quantifier (AtLeast, AtMost, Exactly, Between, …) and exposes .Within(timeout) for asynchronous execution. The assertion polls ITimerMock.ExecutionCount until the quantifier is satisfied or the timeout expires — 30 seconds by default.

await That(timer).Executed().AtLeast(2.Times()).Within(100.Milliseconds());
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories (1)

Showing the top 1 popular GitHub repositories that depend on aweXpect.Testably:

Repository Stars
TestableIO/System.IO.Abstractions
Just like System.Web.Abstractions, but for System.IO. Yay for testable IO access!
Version Downloads Last Updated
0.15.0 0 5/19/2026
0.14.0 30 5/18/2026
0.13.0 4,982 10/25/2025
0.12.0 1,804 9/10/2025
0.11.0 1,388 7/12/2025
0.10.0 740 6/30/2025
0.9.0 1,956 3/17/2025
0.8.0 1,028 3/2/2025
0.7.0 428 3/1/2025
0.6.0 197 2/16/2025
0.5.0 195 2/14/2025
0.5.0-pre.1 407 1/31/2025
0.4.0 265 1/30/2025
0.3.0 649 1/18/2025
0.2.0 1,435 12/13/2024
0.1.0 172 12/10/2024