Skip to main content

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:

Before (TestableIO)
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");
}
}
TestablyM001Migration available.

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​

TestableIOTestably.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 CurrentDirectorynew 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:

Before (TestableIO)
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" });
TestablyM001Migration available.

IMockFileDataAccessor methods on MockFileSystem​

TestableIOTestably.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:

Before (TestableIO)
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 });
TestablyM001Migration available.

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:

Before (TestableIO)
using System.IO.Abstractions.TestingHelpers;

MockFileSystem fs = new MockFileSystem();
DateTimeOffset lastWrite = fs.GetFile("/notes.txt").LastWriteTime;
fs.GetFile("/notes.txt").TextContents = "Updated";
TestablyM001Migration available.