System.IO.Abstractions icon indicating copy to clipboard operation
System.IO.Abstractions copied to clipboard

How to write a test that checks for insufficient space available?

Open FroggieFrog opened this issue 3 years ago • 3 comments

Describe the bug I need to write a test for some logic that checks if there is enough space available on disk.

To Reproduce

logic to test
private IFileSystem _fileSystem;//injected in ctor as = new MockFileSystem() in tests | = new FileSystem() in production

var requiredSpace = calculateActualSize(filePaths);
var availableFreeSpace = getAvailableFreeSpaceOnDisk(driveName);
if (availableFreeSpace < requiredSpace)
{
    //throw exception
}

private long getAvailableFreeSpaceOnDisk(string driveName)
{
    var driveInfo = _fileSystem.DriveInfo.FromDriveName(driveName);
    var result = driveInfo.AvailableFreeSpace;
    return result;
}

test code so far (does not work)
[Fact]
public void RequiredSpaceIsInsufficient_ShouldThrow()
{
    // Arrange
    var fileSystem = new MockFileSystem();    
    fileSystem.AddDirectory(@"Q:\Destination");
    fileSystem.AddFile(@"W:\source\test.txt", new MockFileData(new byte[2]));

    var driveInfo = new MockDriveInfo(fileSystem, "Q");
    driveInfo.AvailableFreeSpace = 1;

    // Act   
    var ex = Record.Exception(() => new ClassToTest(fileSystem).MethodToTest());

    // Assert
    Assert.IsType<ExpectedExceptionType>(ex);
}

Actual behavior The injected IFileSystem has a DriveInfo with AvailableFreeSpace set to 0.

Expected behavior The injected IFileSystem has a DriveInfo with AvailableFreeSpace set to 1.

Additional context I did some search and found a comment on issue #274, but I'm still unable to understand how to write a functioning test.

FroggieFrog avatar Mar 16 '22 09:03 FroggieFrog

This is currently not possible. As mentioned in the issue you linked these properties should actually be read-only.

Would be cool to support this somehow, but I guess it would be quite some effort. I will probably not find the time for implementing this anytime soon, but would be open for a contribution.

fgreinacher avatar Mar 25 '22 19:03 fgreinacher

Thank you for your time and your reply. In the meantime I managed to come up with a workaround. I made my own IFileSystem by inheriting from MockFileSystem and used Moq. Maybe it is useful for someone else.

public class TestClass
{
    [Fact]
    public void CreateBackup_RequiredSpaceIsInsufficient_ShouldReturnFalse()
    {
        // Arrange
        var sourceFilePath = $@"A:\source\test.txt";
        var fileSize = 2;

        //setup DriveInfo for backup
        var mockedDriveInfo = new Mock<IDriveInfo>();
        mockedDriveInfo.Setup(x => x.Name).Returns(() => "Q");
        mockedDriveInfo.Setup(x => x.AvailableFreeSpace).Returns(() => fileSize - 1);

        var mockedDriveInfoFactory = new Mock<IDriveInfoFactory>();
        mockedDriveInfoFactory.Setup(x => x.FromDriveName(It.IsAny<string>())).Returns(() => mockedDriveInfo.Object);

        //add files to backup to FileSystem
        var fileSystem = new MyMockFileSystem(mockedDriveInfoFactory.Object);
        fileSystem.AddFile(sourceFilePath, new MockFileData(new byte[fileSize]));

        // ...
    }
}

internal class MyMockFileSystem : MockFileSystem
{
    private IDriveInfoFactory _driveInfoFactory;

    public MyMockFileSystem(IDriveInfoFactory driveInfoFactoryToUse) : base()
    {
        _driveInfoFactory = driveInfoFactoryToUse;
    }

    public override IDriveInfoFactory DriveInfo => _driveInfoFactory;
}

FroggieFrog avatar Mar 29 '22 10:03 FroggieFrog

In the meantime I managed to come up with a workaround. I made my own IFileSystem by inheriting from MockFileSystem and used Moq. Maybe it is useful for someone else.

Thanks for sharing your solution, looks neat to me!

fgreinacher avatar Apr 03 '22 13:04 fgreinacher

This is addressed in release v20.0.28.

github-actions[bot] avatar Mar 09 '24 16:03 github-actions[bot]