Migrating from TestableIO
The TestablyM001 code fix swaps the using directive from System.IO.Abstractions.TestingHelpers to Testably.Abstractions.Testing and rewrites each call on the MockFileSystem, so one fix migrates the whole file:
using System.Collections.Generic;
using System.IO.Abstractions.TestingHelpers;
public class TempFileCleanerTests
{
[Test]
public async Task Clean_ShouldOnlyDeleteTemporaryFiles()
{
MockFileSystem fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
["/work/report.txt"] = new MockFileData("Quarterly report"),
["/work/cache.tmp"] = new MockFileData(new byte[] { 1, 2, 3 }),
});
fileSystem.AddEmptyFile("/work/empty.tmp");
new TempFileCleaner(fileSystem).Clean("/work");
await That(fileSystem.FileExists("/work/cache.tmp")).IsFalse();
await That(fileSystem.FileExists("/work/empty.tmp")).IsFalse();
await That(fileSystem.GetFile("/work/report.txt").TextContents).IsEqualTo("Quarterly report");
}
}
Supported TestableIO constructs
The tables list the constructs the code fix rewrites. Every other construct of System.IO.Abstractions.TestingHelpers that the analyzer reports needs manual review.
MockFileSystem constructors
| TestableIO | Testably.Abstractions |
|---|---|
new MockFileSystem() | new MockFileSystem() |
new MockFileSystem(IDictionary<string, MockFileData>) | new MockFileSystem() followed by fs.Directory.CreateDirectory(…) for each parent directory and a write call for each file (only as a local declaration in a block) |
new MockFileSystem(MockFileSystemOptions) with CurrentDirectory | new MockFileSystem(o => o.UseCurrentDirectory(…)) (other options have no fix) |
new MockFileSystem(IDictionary<…>, MockFileSystemOptions) | both of the above |
new MockFileSystem(IDictionary<…>, currentDirectory) | both of the above, with o => o.UseCurrentDirectory(currentDirectory) |
The files of the dictionary become statements after the constructor, and the options become a lambda:
using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions.TestingHelpers;
MockFileSystem fs = new MockFileSystem(new Dictionary<string, MockFileData>
{
["/work/config.json"] = new MockFileData("{}") { Attributes = FileAttributes.ReadOnly },
}, new MockFileSystemOptions { CurrentDirectory = "/work" });
IMockFileDataAccessor methods on MockFileSystem
| TestableIO | Testably.Abstractions |
|---|---|
fs.AddFile(path, new MockFileData(text[, encoding])) | fs.File.WriteAllText(path, text[, encoding]) |
fs.AddFile(path, new MockFileData(bytes)) | fs.File.WriteAllBytes(path, bytes) |
fs.AddFile(path, new MockFileData(…) { Attributes = attributes }) | the write call above, followed by fs.File.SetAttributes(path, attributes) (only as a statement in a block) |
fs.AddEmptyFile(path) | fs.File.Create(path).Dispose() |
fs.AddDirectory(path) | fs.Directory.CreateDirectory(path) |
fs.RemoveFile(path) | fs.File.Delete(path) |
fs.MoveDirectory(source, dest) | fs.Directory.Move(source, dest) |
fs.FileExists(path) | fs.File.Exists(path) |
fs.AddDrive(name, mockDriveData) | fs.WithDrive(name, d => d.Set…(…)) (mapped setters) |
fs.AddFilesFromEmbeddedNamespace(path, assembly, prefix) | fs.InitializeEmbeddedResourcesFromAssembly(path, assembly, relativePath: …) (when the assembly arg resolves statically and the prefix starts with the assembly name) |
The contents of the MockFileData select the write method, and the drive data becomes a lambda:
using System.IO.Abstractions.TestingHelpers;
MockFileSystem fs = new MockFileSystem();
fs.AddFile("/notes.txt", new MockFileData("Hello"));
fs.AddFile("/image.png", new MockFileData(new byte[] { 0x89, 0x50 }));
fs.AddEmptyFile("/empty.txt");
fs.AddDrive("D:", new MockDriveData { TotalSize = 1024 });
MockFileData property access
Reads of MockFileData properties (e.g. fs.GetFile(path).LastWriteTime) are routed to the matching Testably.Abstractions file-system call; the time properties are read as UTC (e.g. fs.File.GetLastWriteTimeUtc(path)). Writes of TextContents, Contents and Attributes become fs.File.WriteAllText, fs.File.WriteAllBytes and fs.File.SetAttributes; writes of the time properties have no fix. The code fix only handles the one-shot fs.GetFile(path).Prop shape; property access through a captured reference is left for manual review.
A time property is read as UTC, and a written property becomes a write call:
using System.IO.Abstractions.TestingHelpers;
MockFileSystem fs = new MockFileSystem();
DateTimeOffset lastWrite = fs.GetFile("/notes.txt").LastWriteTime;
fs.GetFile("/notes.txt").TextContents = "Updated";