feat(configmanager): add IFileSystem abstraction
Add file system abstraction to enable testability for file operations. - IFileSystem interface with common file operations - FileSystem implementation wrapping System.IO - Unit tests for FileExists functionality
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
namespace JdeScoping.ConfigManager.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Real file system implementation.
|
||||
/// </summary>
|
||||
public class FileSystem : IFileSystem
|
||||
{
|
||||
public bool FileExists(string path) => File.Exists(path);
|
||||
|
||||
public bool DirectoryExists(string path) => Directory.Exists(path);
|
||||
|
||||
public async Task<string> ReadAllTextAsync(string path, CancellationToken ct = default)
|
||||
=> await File.ReadAllTextAsync(path, ct);
|
||||
|
||||
public async Task WriteAllTextAsync(string path, string content, CancellationToken ct = default)
|
||||
=> await File.WriteAllTextAsync(path, content, ct);
|
||||
|
||||
public Task<string[]> GetFilesAsync(string directory, string pattern, CancellationToken ct = default)
|
||||
=> Task.FromResult(Directory.GetFiles(directory, pattern));
|
||||
|
||||
public async Task CopyFileAsync(string source, string destination, CancellationToken ct = default)
|
||||
{
|
||||
var content = await File.ReadAllBytesAsync(source, ct);
|
||||
await File.WriteAllBytesAsync(destination, content, ct);
|
||||
}
|
||||
|
||||
public Task DeleteFileAsync(string path, CancellationToken ct = default)
|
||||
{
|
||||
File.Delete(path);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public string GetDirectoryName(string path) => Path.GetDirectoryName(path) ?? string.Empty;
|
||||
|
||||
public string GetFileName(string path) => Path.GetFileName(path);
|
||||
|
||||
public string GetFileNameWithoutExtension(string path) => Path.GetFileNameWithoutExtension(path);
|
||||
|
||||
public string Combine(params string[] paths) => Path.Combine(paths);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace JdeScoping.ConfigManager.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Abstraction for file system operations to enable testing.
|
||||
/// </summary>
|
||||
public interface IFileSystem
|
||||
{
|
||||
bool FileExists(string path);
|
||||
bool DirectoryExists(string path);
|
||||
Task<string> ReadAllTextAsync(string path, CancellationToken ct = default);
|
||||
Task WriteAllTextAsync(string path, string content, CancellationToken ct = default);
|
||||
Task<string[]> GetFilesAsync(string directory, string pattern, CancellationToken ct = default);
|
||||
Task CopyFileAsync(string source, string destination, CancellationToken ct = default);
|
||||
Task DeleteFileAsync(string path, CancellationToken ct = default);
|
||||
string GetDirectoryName(string path);
|
||||
string GetFileName(string path);
|
||||
string GetFileNameWithoutExtension(string path);
|
||||
string Combine(params string[] paths);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using JdeScoping.ConfigManager.Services;
|
||||
|
||||
namespace JdeScoping.ConfigManager.Tests.Services;
|
||||
|
||||
public class FileSystemTests
|
||||
{
|
||||
[Fact]
|
||||
public void FileExists_WithExistingFile_ReturnsTrue()
|
||||
{
|
||||
// Arrange
|
||||
var sut = new FileSystem();
|
||||
var tempFile = Path.GetTempFileName();
|
||||
|
||||
try
|
||||
{
|
||||
// Act
|
||||
var result = sut.FileExists(tempFile);
|
||||
|
||||
// Assert
|
||||
result.ShouldBeTrue();
|
||||
}
|
||||
finally
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FileExists_WithNonExistingFile_ReturnsFalse()
|
||||
{
|
||||
// Arrange
|
||||
var sut = new FileSystem();
|
||||
|
||||
// Act
|
||||
var result = sut.FileExists("/nonexistent/path/file.txt");
|
||||
|
||||
// Assert
|
||||
result.ShouldBeFalse();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user