Using System.IO.Abstractions with DirectoryInfo

Viewed 1351

How can I write unit tests using Moq for DirectoryInfo? My class is as below:

public class DataProcessor : IDataProcessor, IDisposable
{
    private ILogger _logger;
        
    DataProcessor(ILogger logger)
    {
        _logger = logger;
    }

    public async Task Run(string filePath)
    {
        var dir = new DirectoryInfo( filePath);
        var filesInDir = dir.GetFiles("*.xml");

        foreach(var filePath in filesInDir)
        {
            // process file
        }   
    }
}

I tried using System.IO.Abstractions and changed my class as below but DirectoryInfo does not work with System.IO.Abstractions

public class DataProcessor : IDataProcessor, IDisposable
{
    private readonly IFileSystem _fileSystem;

    private ILogger _logger;
        
    DataProcessor(ILogger logger) : this(new FileSystem())
    {
        _logger = logger;
    }

    internal DataProcessor(IFileSystem fileSystem)
    {
        _fileSystem = fileSystem;
    }

    public async Task Run(string filePath)
    {
        var dir = new _fileSystem.DirectoryInfo(filePath);// ERROR HERE
        var filesInDir = dir.GetFiles("*.xml");

        foreach(var filePath in filesInDir)
        {
            // process file
        }             
    }
}

The error I get is

The name or namespace name '_fileSystem' does not exist.

Is this because I am not doing it right or this can't be done?

1 Answers

You can instantiate an IDirectoryInfo object using:

IDirectoryInfo directory = _fileSystem.DirectoryInfo.FromDirectoryName(filePath);

So your full code would look like:

public class DataProcessor : IDataProcessor, IDisposable
{
    private readonly IFileSystem _fileSystem;
    private ILogger _logger;
    
    DataProcessor(ILogger logger) : this(new FileSystem())
    {
        _logger = logger;
    }

    internal DataProcessor(IFileSystem fileSystem)
    {
        _fileSystem = fileSystem;
    }

    public async Task Run(string filePath)
    {
        var dir = _fileSystem.DirectoryInfo.FromDirectoryName(filePath);
        var filesInDir = dir.GetFiles("*.xml");

        foreach(var filePath in filesInDir)
        {
            // process file
        }           
    }
}

As for your unit tests, I recommend following the System.IO.Abstractions example shown on their GitHub page. You can mock your file system like this:

[Test]
public void DataProcessorTestName()
{
    // Arrange
    var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
    {
        { @"c:\myfile.txt", new MockFileData("Testing is meh.") },
        { @"c:\demo\jQuery.js", new MockFileData("some js") },
        { @"c:\demo\image.gif", new MockFileData(new byte[] { 0x12, 0x34, 0x56, 0xd2 }) }
    });
    var dataProcessor = new DataProcessor(fileSystem);

    // Test logic here...
}
Related