From 07eaf01a7a1ef0fa87636a3bcceba3caa16b6cd6 Mon Sep 17 00:00:00 2001 From: Joachim Breitsprecher Date: Wed, 18 Feb 2026 14:15:57 +0100 Subject: [PATCH 1/4] Add test case for issue #941 --- .../FileSystemInitializerTests.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Tests/Testably.Abstractions.Testing.Tests/FileSystemInitializer/FileSystemInitializerTests.cs b/Tests/Testably.Abstractions.Testing.Tests/FileSystemInitializer/FileSystemInitializerTests.cs index 295c56cef..2de1954af 100644 --- a/Tests/Testably.Abstractions.Testing.Tests/FileSystemInitializer/FileSystemInitializerTests.cs +++ b/Tests/Testably.Abstractions.Testing.Tests/FileSystemInitializer/FileSystemInitializerTests.cs @@ -125,6 +125,25 @@ public async Task With_FilesAndDirectories_ShouldBothBeCreated(string fileName, await That(fileSystem.File.Exists(fileName)).IsTrue(); await That(fileSystem.Directory.Exists(directoryName)).IsTrue(); } + + [Theory] + [AutoData] + public async Task With_FilesAndDirectoriesWithAbsolutePath_ShouldBeCreatedAtTheCorrectPath( + string level1, string level2, string fileName) + { + string directoryPath = Path.Combine(level1, level2); + string filePath = Path.Combine(directoryPath, fileName); + FileDescription fileDescription = new(fileName); + DirectoryDescription directoryDescription = new(directoryPath, fileDescription); + MockFileSystem fileSystem = new(); + IFileSystemInitializer sut = fileSystem.Initialize(); + + sut.With(directoryDescription); + + await That(fileSystem.Statistics.TotalCount).IsEqualTo(0); + await That(fileSystem.Directory.Exists(directoryPath)).IsTrue(); + await That(fileSystem.File.Exists(filePath)).IsTrue(); + } [Theory] [AutoData] From 72645f1d7aa4e3d2cd5d5da96b638fc441b77877 Mon Sep 17 00:00:00 2001 From: Joachim Breitsprecher Date: Thu, 19 Feb 2026 16:49:42 +0100 Subject: [PATCH 2/4] Preliminary fix for #941 --- .../Initializer/FileSystemInitializer.cs | 11 +++++++++- .../FileSystemInitializerTests.cs | 20 ++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Source/Testably.Abstractions.Testing/Initializer/FileSystemInitializer.cs b/Source/Testably.Abstractions.Testing/Initializer/FileSystemInitializer.cs index e88da1161..50d7d9fb2 100644 --- a/Source/Testably.Abstractions.Testing/Initializer/FileSystemInitializer.cs +++ b/Source/Testably.Abstractions.Testing/Initializer/FileSystemInitializer.cs @@ -37,6 +37,15 @@ internal FileSystemInitializer(FileSystemInitializer parent, _basePath = FileSystem.Path.Combine(parent._basePath, subdirectory.Name); } + internal FileSystemInitializer(FileSystemInitializer parent, + string subdirectory) + { + FileSystem = parent.FileSystem; + using IDisposable release = FileSystem.IgnoreStatistics(); + _initializedFileSystemInfos = parent._initializedFileSystemInfos; + _basePath = FileSystem.Path.Combine(parent._basePath, subdirectory); + } + #region IFileSystemInitializer Members /// @@ -146,7 +155,7 @@ private IDirectoryInfo WithDirectory(DirectoryDescription directory) FileSystem.Directory.CreateDirectory(directoryInfo.FullName); - FileSystemInitializer subdirectoryInitializer = new(this, directoryInfo); + FileSystemInitializer subdirectoryInitializer = new(this, directory.Name); foreach (FileSystemInfoDescription children in directory.Children) { subdirectoryInitializer.WithFileOrDirectory(children); diff --git a/Tests/Testably.Abstractions.Testing.Tests/FileSystemInitializer/FileSystemInitializerTests.cs b/Tests/Testably.Abstractions.Testing.Tests/FileSystemInitializer/FileSystemInitializerTests.cs index 2de1954af..8010fa354 100644 --- a/Tests/Testably.Abstractions.Testing.Tests/FileSystemInitializer/FileSystemInitializerTests.cs +++ b/Tests/Testably.Abstractions.Testing.Tests/FileSystemInitializer/FileSystemInitializerTests.cs @@ -128,7 +128,7 @@ public async Task With_FilesAndDirectories_ShouldBothBeCreated(string fileName, [Theory] [AutoData] - public async Task With_FilesAndDirectoriesWithAbsolutePath_ShouldBeCreatedAtTheCorrectPath( + public async Task With_FilesAndDirectoriesWithMultiplePathComponents_ShouldBeCreatedAtTheCorrectPath( string level1, string level2, string fileName) { string directoryPath = Path.Combine(level1, level2); @@ -205,6 +205,24 @@ public async Task WithFile_MissingDirectory_ShouldCreateDirectory(string directo await That(fileSystem.Directory.Exists(directoryPath)).IsTrue(); } + [Theory] + [AutoData] + public async Task WithFile_MultiplePathComponents_ShouldCreateDirectories(string level1, + string level2, string level3, string fileName) + { + string path = Path.Combine(level1, level2, level3, fileName); + MockFileSystem fileSystem = new(); + IFileSystemInitializer sut = fileSystem.Initialize(); + + sut.WithFile(path); + + await That(fileSystem.Statistics.TotalCount).IsEqualTo(0); + await That(fileSystem.File.Exists(path)).IsTrue(); + await That(fileSystem.Directory.Exists(level1)).IsTrue(); + await That(fileSystem.Directory.Exists(Path.Combine(level1, level2))).IsTrue(); + await That(fileSystem.Directory.Exists(Path.Combine(level1, level2, level3))).IsTrue(); + } + [Theory] [AutoData] public async Task WithSubdirectories_ShouldCreateAllDirectories(string[] paths) From 262f070f4a15f1e0697b27f05f391f10d39365b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Sat, 7 Mar 2026 14:23:43 +0100 Subject: [PATCH 3/4] Suggestion to get rid of the constructor that takes a `DirectoryInfo` --- .../Initializer/DirectoryInitializer.cs | 5 ++- .../Initializer/FileSystemInitializer.cs | 32 +++++++------------ 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/Source/Testably.Abstractions.Testing/Initializer/DirectoryInitializer.cs b/Source/Testably.Abstractions.Testing/Initializer/DirectoryInitializer.cs index 591bf2e24..e7f012146 100644 --- a/Source/Testably.Abstractions.Testing/Initializer/DirectoryInitializer.cs +++ b/Source/Testably.Abstractions.Testing/Initializer/DirectoryInitializer.cs @@ -1,4 +1,5 @@ using System; +using Testably.Abstractions.Testing.Helpers; namespace Testably.Abstractions.Testing.Initializer; @@ -24,7 +25,9 @@ public DirectoryInitializer(FileSystemInitializer initializer, public IFileSystemDirectoryInitializer Initialized( Action> subdirectoryInitializer) { - FileSystemInitializer initializer = new(this, Directory); + using IDisposable release = FileSystem.IgnoreStatistics(); + FileSystemInitializer initializer = + new(this, FileSystem.Path.Combine(BasePath, Directory.Name)); subdirectoryInitializer.Invoke(initializer); return this; } diff --git a/Source/Testably.Abstractions.Testing/Initializer/FileSystemInitializer.cs b/Source/Testably.Abstractions.Testing/Initializer/FileSystemInitializer.cs index 50d7d9fb2..7c26e11c8 100644 --- a/Source/Testably.Abstractions.Testing/Initializer/FileSystemInitializer.cs +++ b/Source/Testably.Abstractions.Testing/Initializer/FileSystemInitializer.cs @@ -10,14 +10,14 @@ internal class FileSystemInitializer : IFileSystemInitializer where TFileSystem : IFileSystem { - private readonly string _basePath; + protected string BasePath { get; } private readonly Dictionary _initializedFileSystemInfos = new(); public FileSystemInitializer(TFileSystem fileSystem, string basePath) { - _basePath = basePath; + BasePath = basePath; FileSystem = fileSystem; } @@ -25,32 +25,23 @@ protected FileSystemInitializer(FileSystemInitializer parent) { FileSystem = parent.FileSystem; _initializedFileSystemInfos = parent._initializedFileSystemInfos; - _basePath = parent._basePath; + BasePath = parent.BasePath; } internal FileSystemInitializer(FileSystemInitializer parent, - IDirectoryInfo subdirectory) + string basePath) { FileSystem = parent.FileSystem; using IDisposable release = FileSystem.IgnoreStatistics(); _initializedFileSystemInfos = parent._initializedFileSystemInfos; - _basePath = FileSystem.Path.Combine(parent._basePath, subdirectory.Name); - } - - internal FileSystemInitializer(FileSystemInitializer parent, - string subdirectory) - { - FileSystem = parent.FileSystem; - using IDisposable release = FileSystem.IgnoreStatistics(); - _initializedFileSystemInfos = parent._initializedFileSystemInfos; - _basePath = FileSystem.Path.Combine(parent._basePath, subdirectory); + BasePath = basePath; } #region IFileSystemInitializer Members /// public IDirectoryInfo BaseDirectory - => FileSystem.DirectoryInfo.New(_basePath); + => FileSystem.DirectoryInfo.New(BasePath); /// public TFileSystem FileSystem { get; } @@ -87,7 +78,7 @@ public IFileSystemFileInitializer WithAFile(string? extension = nul fileName = $"{random.GenerateFileName()}-{random.Next(10000)}.{random.GenerateFileExtension(extension)}"; } while (FileSystem.File.Exists( - FileSystem.Path.Combine(_basePath, fileName))); + FileSystem.Path.Combine(BasePath, fileName))); return WithFile(fileName); } @@ -103,7 +94,7 @@ public IFileSystemDirectoryInitializer WithASubdirectory() directoryName = $"{random.GenerateFileName()}-{random.Next(10000)}"; } while (FileSystem.Directory.Exists( - FileSystem.Path.Combine(_basePath, directoryName))); + FileSystem.Path.Combine(BasePath, directoryName))); return WithSubdirectory(directoryName); } @@ -140,7 +131,7 @@ private IDirectoryInfo WithDirectory(DirectoryDescription directory) { using IDisposable release = FileSystem.IgnoreStatistics(); IDirectoryInfo directoryInfo = FileSystem.DirectoryInfo.New( - FileSystem.Path.Combine(_basePath, directory.Name)); + FileSystem.Path.Combine(BasePath, directory.Name)); if (directoryInfo.Exists) { throw new TestingException( @@ -155,7 +146,8 @@ private IDirectoryInfo WithDirectory(DirectoryDescription directory) FileSystem.Directory.CreateDirectory(directoryInfo.FullName); - FileSystemInitializer subdirectoryInitializer = new(this, directory.Name); + FileSystemInitializer subdirectoryInitializer = new(this, + FileSystem.Path.Combine(BasePath, directory.Name)); foreach (FileSystemInfoDescription children in directory.Children) { subdirectoryInitializer.WithFileOrDirectory(children); @@ -173,7 +165,7 @@ private IFileInfo WithFile(FileDescription file) { using IDisposable release = FileSystem.IgnoreStatistics(); IFileInfo fileInfo = FileSystem.FileInfo.New( - FileSystem.Path.Combine(_basePath, file.Name)); + FileSystem.Path.Combine(BasePath, file.Name)); if (fileInfo.Exists) { throw new TestingException( From e7ed04b67a39e99e18f0882397815fb2562acf34 Mon Sep 17 00:00:00 2001 From: Joachim Breitsprecher Date: Sat, 7 Mar 2026 23:11:43 +0100 Subject: [PATCH 4/4] Add test case with absolute path to more closely align with #941 --- .../FileSystemInitializerTests.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Tests/Testably.Abstractions.Testing.Tests/FileSystemInitializer/FileSystemInitializerTests.cs b/Tests/Testably.Abstractions.Testing.Tests/FileSystemInitializer/FileSystemInitializerTests.cs index 8010fa354..119d9be5f 100644 --- a/Tests/Testably.Abstractions.Testing.Tests/FileSystemInitializer/FileSystemInitializerTests.cs +++ b/Tests/Testably.Abstractions.Testing.Tests/FileSystemInitializer/FileSystemInitializerTests.cs @@ -145,6 +145,25 @@ public async Task With_FilesAndDirectoriesWithMultiplePathComponents_ShouldBeCre await That(fileSystem.File.Exists(filePath)).IsTrue(); } + [Theory] + [AutoData] + public async Task With_AbsoluteDirectoryWithChildren_ShouldBeCreatedAtTheCorrectPath( + string level1, string level2, string fileName) + { + string directoryPath = Path.GetFullPath(Path.Combine(level1, level2)); + string filePath = Path.Combine(directoryPath, fileName); + FileDescription fileDescription = new(fileName); + DirectoryDescription directoryDescription = new(directoryPath, fileDescription); + MockFileSystem fileSystem = new(); + IFileSystemInitializer sut = fileSystem.Initialize(); + + sut.With(directoryDescription); + + await That(fileSystem.Statistics.TotalCount).IsEqualTo(0); + await That(fileSystem.Directory.Exists(directoryPath)).IsTrue(); + await That(fileSystem.File.Exists(filePath)).IsTrue(); + } + [Theory] [AutoData] public async Task WithFile_ExistingDirectory_ShouldThrowTestingException(string path)