FileSystemWatcher
MockFileSystem ships a fully functional FileSystemWatcher replacement. It fires the same events as the real one and, crucially, it fires the OS-specific events that the real watcher fires on Linux, Windows and macOS.
Basic usage
MockFileSystem fileSystem = new();
fileSystem.Initialize().WithSubdirectory("vault");
fileSystem.File.WriteAllBytes("vault/red-square.png", []);
using IFileSystemWatcher watcher = fileSystem.FileSystemWatcher.New("vault");
ManualResetEventSlim artworkRemoved = new();
watcher.Deleted += (_, _) => artworkRemoved.Set();
watcher.EnableRaisingEvents = true;
fileSystem.File.Delete("vault/red-square.png");
await That(artworkRemoved.Wait(TimeSpan.FromSeconds(1))).IsTrue();
Reacting to triggered events from a test
MockFileSystem.Watcher.OnTriggered(...) returns an awaitable callback that fires after every IFileSystemWatcher event. Use it to assert what a watcher saw without subscribing to the event yourself:
MockFileSystem fileSystem = new();
fileSystem.Initialize().WithSubdirectory("vault");
using IFileSystemWatcher watcher = fileSystem.FileSystemWatcher.New("vault");
watcher.EnableRaisingEvents = true;
using IAwaitableCallback<WatcherChangeDescription> triggered = fileSystem.Watcher.OnTriggered();
fileSystem.File.WriteAllBytes("vault/blue-circles.png", []);
WatcherChangeDescription[] events = triggered.Wait(count: 1);
Which events are raised
When an entry is moved, the events depend on where it comes from and where it goes, relative to the watched path:
storage/ ← Outside
vault/ ← the watched path
├── red-square.png ← Inside
└── sketches/
├── blue-circles.png ← Nested
└── drafts/
└── yellow-lines.png ← Deep
_ stands for "nothing", i.e. the entry is created (_ → Inside) or deleted (Inside → _), and - means no event is raised. Pick the value of IncludeSubdirectories:
- IncludeSubdirectories = false
- IncludeSubdirectories = true
| From → To | Linux | Windows | macOS |
|---|---|---|---|
_ → Inside | Created | Created | Created |
Inside → _ | Deleted | Deleted | Deleted |
_ → Nested | - | - | - |
Nested → _ | - | - | - |
_ → Deep | - | - | - |
Deep → _ | - | - | - |
| Outside → Inside | Created | Created | Created |
| Inside → Inside | Renamed | Renamed | Renamed |
| Inside → Outside | Deleted | Deleted | Deleted |
| Outside → Nested | - | - | - |
| Nested → Nested | - | - | - |
| Nested → Outside | - | - | - |
| Outside → Deep | - | - | - |
| Deep → Deep | - | - | - |
| Deep → Outside | - | - | - |
| Inside → Nested | Deleted | Deleted | Renamed |
| Inside → Deep | Deleted | Deleted | Renamed |
| Nested → Inside | Created | Created | Created |
| Deep → Inside | Created | Created | Created |
| Nested → Deep | - | - | - |
| Deep → Nested | - | - | - |
| From → To | Linux | Windows | macOS |
|---|---|---|---|
_ → Inside | Created | Created | Created |
Inside → _ | Deleted | Deleted | Deleted |
_ → Nested | Created | Created | Created |
Nested → _ | Deleted | Deleted | Deleted |
_ → Deep | Created | Created | Created |
Deep → _ | Deleted | Deleted | Deleted |
| Outside → Inside | Created | Created | Created |
| Inside → Inside | Renamed | Renamed | Renamed |
| Inside → Outside | Deleted | Deleted | Deleted |
| Outside → Nested | Created | Created | Created |
| Nested → Nested | Renamed | Renamed | Renamed |
| Nested → Outside | Deleted | Deleted | Deleted |
| Outside → Deep | Created | Created | Created |
| Deep → Deep | Renamed | Renamed | Renamed |
| Deep → Outside | Deleted | Deleted | Deleted |
| Inside → Nested | Renamed | Deleted + Created | Renamed |
| Inside → Deep | Renamed | Deleted + Created | Renamed |
| Nested → Inside | Renamed | Deleted + Created | Renamed |
| Deep → Inside | Renamed | Deleted + Created | Renamed |
| Nested → Deep | Renamed | Deleted + Created | Renamed |
| Deep → Nested | Renamed | Deleted + Created | Renamed |
The mock follows the host OS, or the OS chosen with SimulatingOperatingSystem.