如何使用System.IO.Abstractions中的FileSystemWatcher来监视模拟文件系统?

时间:2017-10-31 09:15:13

标签: c# filesystems filesystemwatcher

我正在尝试创建一个类来监控Linux上的USB设备到达和删除。在Linux上,USB设备表示为/dev/bus/usb下的设备文件,这些设备文件是为响应这些事件而创建/删除的。

跟踪这些事件似乎是使用FileSystemWatcher的最佳方法。为了使类可测试,我正在使用System.IO.Abstractions并在构造期间向类中注入IFileSystem的实例。我想要的是创建一个行为类似于FileSystemWatcher的东西,但监视注入IFileSystem的更改,而不是直接监视真实文件系统。

FileSystemWatcherBase查看FileSystemWatcherWrapperSystem.IO.Abstractions,我不知道该怎么做。目前我有这个(我知道这是错的):

public DevMonitor(
    [NotNull] IFileSystem fileSystem,
    [NotNull] IDeviceFileParser deviceFileParser,
    [NotNull] ILogger logger,
    [NotNull] string devDirectoryPath = DefaultDevDirectoryPath)
{
    Raise.ArgumentNullException.IfIsNull(logger, nameof(logger));
    Raise.ArgumentNullException.IfIsNull(devDirectoryPath, nameof(devDirectoryPath));

    _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
    _deviceFileParser = deviceFileParser ?? throw new ArgumentNullException(nameof(deviceFileParser));
    _logger = logger.ForContext<DevMonitor>();
    _watcher = new FileSystemWatcherWrapper(devDirectoryPath);
}

1 个答案:

答案 0 :(得分:2)

鉴于const express = require('express'); const mysql = require('mysql'); const app = express(); const connection = mysql.createConnection({ host: '127.0.0.1', port: 5000, user: 'root', password: 'password' }); connection.query('CREATE DATABASE IF NOT EXISTS test', function (err) { if (err) throw err; console.log("database created"); connection.query('USE test', function (err) { if (err) throw err; connection.query('CREATE TABLE IF NOT EXISTS users(' + 'id INT NOT NULL AUTO_INCREMENT,' + 'PRIMARY KEY(id),' + 'name VARCHAR(30)' + ')', function (err) { if (err) throw err; }); }); }); // connection.end(); app.get('/', function (req, res) { res.sendFile(__dirname + '/index.html'); console.log("send file index.html"); }); app.post('/users', function (req, res) { connection.query('INSERT INTO users SET ?', req.body, function (err, result) { if (err) throw err; res.send('User added to database with ID: ' + result.insertId); } ); }); const server = app.listen(5000, "127.0.0.1", function () { const host = server.address().address; const port = server.address().port; console.log("app listening at http://%s:%s", host, port) }); 似乎还不支持这一点,我接受了这个:

我定义了System.IO.Abstractions扩展IWatchableFileSystem的接口:

IFileSystem

出于制作目的,我将其实现为/// <summary> /// Represents a(n) <see cref="IFileSystem" /> that can be watched for changes. /// </summary> public interface IWatchableFileSystem : IFileSystem { /// <summary> /// Creates a <c>FileSystemWatcher</c> that can be used to monitor changes to this file system. /// </summary> /// <returns>A <c>FileSystemWatcher</c>.</returns> FileSystemWatcherBase CreateWatcher(); }

WatchableFileSystem

在我的单元测试类中,我将其实现为/// <inheritdoc /> public sealed class WatchableFileSystem : IWatchableFileSystem { private readonly IFileSystem _fileSystem; /// <summary> /// Initializes a new instance of the <see cref="WatchableFileSystem" /> class. /// </summary> public WatchableFileSystem() => _fileSystem = new FileSystem(); /// <inheritdoc /> public DirectoryBase Directory => _fileSystem.Directory; /// <inheritdoc /> public IDirectoryInfoFactory DirectoryInfo => _fileSystem.DirectoryInfo; /// <inheritdoc /> public IDriveInfoFactory DriveInfo => _fileSystem.DriveInfo; /// <inheritdoc /> public FileBase File => _fileSystem.File; /// <inheritdoc /> public IFileInfoFactory FileInfo => _fileSystem.FileInfo; /// <inheritdoc /> public PathBase Path => _fileSystem.Path; /// <inheritdoc /> public FileSystemWatcherBase CreateWatcher() => new FileSystemWatcher(); } ,它将MockWatchableFileSystemMockFileSystem作为属性公开,我可以用它来安排&amp;在我的测试中断言:

Mock<FileSystemWatcherBase>

最后,在我的客户端类中,我可以这样做:

private class MockWatchableFileSystem : IWatchableFileSystem
{
    /// <inheritdoc />
    public MockWatchableFileSystem()
    {
        Watcher = new Mock<FileSystemWatcherBase>();
        AsMock = new MockFileSystem();

        AsMock.AddDirectory("/dev/bus/usb");
        Watcher.SetupAllProperties();
    }

    public MockFileSystem AsMock { get; }

    /// <inheritdoc />
    public DirectoryBase Directory => AsMock.Directory;

    /// <inheritdoc />
    public IDirectoryInfoFactory DirectoryInfo => AsMock.DirectoryInfo;

    /// <inheritdoc />
    public IDriveInfoFactory DriveInfo => AsMock.DriveInfo;

    /// <inheritdoc />
    public FileBase File => AsMock.File;

    /// <inheritdoc />
    public IFileInfoFactory FileInfo => AsMock.FileInfo;

    /// <inheritdoc />
    public PathBase Path => AsMock.Path;

    public Mock<FileSystemWatcherBase> Watcher { get; }

    /// <inheritdoc />
    public FileSystemWatcherBase CreateWatcher() => Watcher.Object;
}

在测试期间,客户端获取public DevMonitor( [NotNull] IWatchableFileSystem fileSystem, [NotNull] IDeviceFileParser deviceFileParser, [NotNull] ILogger logger, [NotNull] string devDirectoryPath = DefaultDevDirectoryPath) { // ... _watcher = fileSystem.CreateWatcher(); _watcher.IncludeSubdirectories = true; _watcher.EnableRaisingEvents = true; _watcher.Path = devDirectoryPath; } 包装IWatchableFileSystem并返回MockFileSystem的模拟实例。在制作过程中,它会FileSystemWatcherBase包裹IWatchableFileSystem并生成FileSystem的唯一实例。