diff --git a/src/System.IO.Abstractions.TestingHelpers/MockDirectoryData.cs b/src/System.IO.Abstractions.TestingHelpers/MockDirectoryData.cs
index 7cc83e102..28d8925f1 100644
--- a/src/System.IO.Abstractions.TestingHelpers/MockDirectoryData.cs
+++ b/src/System.IO.Abstractions.TestingHelpers/MockDirectoryData.cs
@@ -11,9 +11,6 @@ public class MockDirectoryData : MockFileData
[NonSerialized]
private DirectorySecurity accessControl;
- ///
- public override bool IsDirectory { get { return true; } }
-
///
public MockDirectoryData() : base(string.Empty)
{
diff --git a/src/System.IO.Abstractions.TestingHelpers/MockDirectoryInfo.cs b/src/System.IO.Abstractions.TestingHelpers/MockDirectoryInfo.cs
index 61d17c99e..1fa30a351 100644
--- a/src/System.IO.Abstractions.TestingHelpers/MockDirectoryInfo.cs
+++ b/src/System.IO.Abstractions.TestingHelpers/MockDirectoryInfo.cs
@@ -13,6 +13,8 @@ public class MockDirectoryInfo : DirectoryInfoBase
private readonly IMockFileDataAccessor mockFileDataAccessor;
private readonly string directoryPath;
private readonly string originalPath;
+ private MockFileData cachedMockFileData;
+ private bool refreshOnNextRead;
///
/// Initializes a new instance of the class.
@@ -33,6 +35,7 @@ public MockDirectoryInfo(IMockFileDataAccessor mockFileDataAccessor, string dire
directoryPath = directoryPath.TrimEnd(' ');
}
this.directoryPath = directoryPath;
+ Refresh();
}
///
@@ -44,7 +47,7 @@ public override void Delete()
///
public override void Refresh()
{
- // Nothing to do here. Mock file system is always up-to-date.
+ cachedMockFileData = mockFileDataAccessor.GetFile(directoryPath)?.Clone();
}
///
@@ -71,7 +74,7 @@ public override DateTime CreationTimeUtc
///
public override bool Exists
{
- get { return mockFileDataAccessor.Directory.Exists(FullName); }
+ get { return GetMockFileDataForRead() != MockFileData.NullObject; }
}
///
@@ -380,11 +383,17 @@ public override IDirectoryInfo Root
private MockFileData GetMockFileDataForRead()
{
- return mockFileDataAccessor.GetFile(directoryPath) ?? MockFileData.NullObject;
+ if (refreshOnNextRead)
+ {
+ Refresh();
+ refreshOnNextRead = false;
+ }
+ return cachedMockFileData ?? MockFileData.NullObject;
}
private MockFileData GetMockFileDataForWrite()
{
+ refreshOnNextRead = true;
return mockFileDataAccessor.GetFile(directoryPath)
?? throw CommonExceptions.FileNotFound(directoryPath);
}
diff --git a/src/System.IO.Abstractions.TestingHelpers/MockFileData.cs b/src/System.IO.Abstractions.TestingHelpers/MockFileData.cs
index 213c9ed8b..84f9532dc 100644
--- a/src/System.IO.Abstractions.TestingHelpers/MockFileData.cs
+++ b/src/System.IO.Abstractions.TestingHelpers/MockFileData.cs
@@ -42,7 +42,7 @@ public class MockFileData
///
/// Gets a value indicating whether the is a directory or not.
///
- public virtual bool IsDirectory { get { return false; } }
+ public bool IsDirectory { get { return Attributes.HasFlag(FileAttributes.Directory); } }
///
/// Initializes a new instance of the class with an empty content.
@@ -183,5 +183,10 @@ internal void CheckFileAccess(string path, FileAccess access)
throw CommonExceptions.ProcessCannotAccessFileInUse(path);
}
}
+
+ internal virtual MockFileData Clone()
+ {
+ return new MockFileData(this);
+ }
}
}
diff --git a/src/System.IO.Abstractions.TestingHelpers/MockFileInfo.cs b/src/System.IO.Abstractions.TestingHelpers/MockFileInfo.cs
index ea6e63685..ad8d4c58e 100644
--- a/src/System.IO.Abstractions.TestingHelpers/MockFileInfo.cs
+++ b/src/System.IO.Abstractions.TestingHelpers/MockFileInfo.cs
@@ -10,7 +10,9 @@ public class MockFileInfo : FileInfoBase
{
private readonly IMockFileDataAccessor mockFileSystem;
private string path;
- private string originalPath;
+ private readonly string originalPath;
+ private MockFileData cachedMockFileData;
+ private bool refreshOnNextRead;
///
public MockFileInfo(IMockFileDataAccessor mockFileSystem, string path) : base(mockFileSystem?.FileSystem)
@@ -18,12 +20,7 @@ public MockFileInfo(IMockFileDataAccessor mockFileSystem, string path) : base(mo
this.mockFileSystem = mockFileSystem ?? throw new ArgumentNullException(nameof(mockFileSystem));
this.originalPath = path ?? throw new ArgumentNullException(nameof(path));
this.path = mockFileSystem.Path.GetFullPath(path);
-
- }
-
- MockFileData MockFileData
- {
- get { return mockFileSystem.GetFile(path); }
+ Refresh();
}
///
@@ -35,7 +32,7 @@ public override void Delete()
///
public override void Refresh()
{
- // Nothing to do here. Mock file system is always up-to-date.
+ cachedMockFileData = mockFileSystem.GetFile(path)?.Clone();
}
///
@@ -43,19 +40,13 @@ public override FileAttributes Attributes
{
get
{
- if (MockFileData == null)
- {
- throw CommonExceptions.FileNotFound(path);
- }
- return MockFileData.Attributes;
+ var mockFileData = GetMockFileDataForRead();
+ return mockFileData.Attributes;
}
set
{
- if (MockFileData == null)
- {
- throw CommonExceptions.FileNotFound(path);
- }
- MockFileData.Attributes = value;
+ var mockFileData = GetMockFileDataForWrite();
+ mockFileData.Attributes = value;
}
}
@@ -64,19 +55,13 @@ public override DateTime CreationTime
{
get
{
- if (MockFileData == null)
- {
- throw CommonExceptions.FileNotFound(path);
- }
- return MockFileData.CreationTime.DateTime;
+ var mockFileData = GetMockFileDataForRead();
+ return mockFileData.CreationTime.DateTime;
}
set
{
- if (MockFileData == null)
- {
- throw CommonExceptions.FileNotFound(path);
- }
- MockFileData.CreationTime = value;
+ var mockFileData = GetMockFileDataForWrite();
+ mockFileData.CreationTime = value;
}
}
@@ -85,20 +70,24 @@ public override DateTime CreationTimeUtc
{
get
{
- if (MockFileData == null) throw CommonExceptions.FileNotFound(path);
- return MockFileData.CreationTime.UtcDateTime;
+ var mockFileData = GetMockFileDataForRead();
+ return mockFileData.CreationTime.UtcDateTime;
}
set
{
- if (MockFileData == null) throw CommonExceptions.FileNotFound(path);
- MockFileData.CreationTime = value.ToLocalTime();
+ var mockFileData = GetMockFileDataForWrite();
+ mockFileData.CreationTime = value.ToLocalTime();
}
}
///
public override bool Exists
{
- get { return MockFileData != null && !MockFileData.IsDirectory; }
+ get
+ {
+ var mockFileData = GetMockFileDataForRead(throwIfNotExisting: false);
+ return mockFileData != null && !mockFileData.IsDirectory;
+ }
}
///
@@ -123,13 +112,13 @@ public override DateTime LastAccessTime
{
get
{
- if (MockFileData == null) throw CommonExceptions.FileNotFound(path);
- return MockFileData.LastAccessTime.DateTime;
+ var mockFileData = GetMockFileDataForRead();
+ return mockFileData.LastAccessTime.DateTime;
}
set
{
- if (MockFileData == null) throw CommonExceptions.FileNotFound(path);
- MockFileData.LastAccessTime = value;
+ var mockFileData = GetMockFileDataForWrite();
+ mockFileData.LastAccessTime = value;
}
}
@@ -138,13 +127,13 @@ public override DateTime LastAccessTimeUtc
{
get
{
- if (MockFileData == null) throw CommonExceptions.FileNotFound(path);
- return MockFileData.LastAccessTime.UtcDateTime;
+ var mockFileData = GetMockFileDataForRead();
+ return mockFileData.LastAccessTime.UtcDateTime;
}
set
{
- if (MockFileData == null) throw CommonExceptions.FileNotFound(path);
- MockFileData.LastAccessTime = value;
+ var mockFileData = GetMockFileDataForWrite();
+ mockFileData.LastAccessTime = value;
}
}
@@ -153,13 +142,13 @@ public override DateTime LastWriteTime
{
get
{
- if (MockFileData == null) throw CommonExceptions.FileNotFound(path);
- return MockFileData.LastWriteTime.DateTime;
+ var mockFileData = GetMockFileDataForRead();
+ return mockFileData.LastWriteTime.DateTime;
}
set
{
- if (MockFileData == null) throw CommonExceptions.FileNotFound(path);
- MockFileData.LastWriteTime = value;
+ var mockFileData = GetMockFileDataForWrite();
+ mockFileData.LastWriteTime = value;
}
}
@@ -168,13 +157,13 @@ public override DateTime LastWriteTimeUtc
{
get
{
- if (MockFileData == null) throw CommonExceptions.FileNotFound(path);
- return MockFileData.LastWriteTime.UtcDateTime;
+ var mockFileData = GetMockFileDataForRead();
+ return mockFileData.LastWriteTime.UtcDateTime;
}
set
{
- if (MockFileData == null) throw CommonExceptions.FileNotFound(path);
- MockFileData.LastWriteTime = value.ToLocalTime();
+ var mockFileData = GetMockFileDataForWrite();
+ mockFileData.LastWriteTime = value.ToLocalTime();
}
}
@@ -201,7 +190,11 @@ public override IFileInfo CopyTo(string destFileName, bool overwrite)
{
if (!Exists)
{
- if (MockFileData == null) throw CommonExceptions.FileNotFound(FullName);
+ var mockFileData = GetMockFileDataForRead(throwIfNotExisting: false);
+ if (mockFileData == null)
+ {
+ throw CommonExceptions.FileNotFound(FullName);
+ }
}
if (destFileName == FullName)
{
@@ -226,17 +219,15 @@ public override StreamWriter CreateText()
///
public override void Decrypt()
{
- if (MockFileData == null) throw CommonExceptions.FileNotFound(path);
-
- MockFileData.Attributes &= ~FileAttributes.Encrypted;
+ var mockFileData = GetMockFileDataForWrite();
+ mockFileData.Attributes &= ~FileAttributes.Encrypted;
}
///
public override void Encrypt()
{
- if (MockFileData == null) throw CommonExceptions.FileNotFound(path);
-
- MockFileData.Attributes |= FileAttributes.Encrypted;
+ var mockFileData = GetMockFileDataForWrite();
+ mockFileData.Attributes |= FileAttributes.Encrypted;
}
///
@@ -341,25 +332,19 @@ public override bool IsReadOnly
{
get
{
- if (MockFileData == null)
- {
- throw CommonExceptions.FileNotFound(path);
- }
- return (MockFileData.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly;
+ var mockFileData = GetMockFileDataForRead();
+ return (mockFileData.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly;
}
set
{
- if (MockFileData == null)
- {
- throw CommonExceptions.FileNotFound(path);
- }
+ var mockFileData = GetMockFileDataForWrite();
if (value)
{
- MockFileData.Attributes |= FileAttributes.ReadOnly;
+ mockFileData.Attributes |= FileAttributes.ReadOnly;
}
else
{
- MockFileData.Attributes &= ~FileAttributes.ReadOnly;
+ mockFileData.Attributes &= ~FileAttributes.ReadOnly;
}
}
}
@@ -369,11 +354,12 @@ public override long Length
{
get
{
- if (MockFileData == null || MockFileData.IsDirectory)
+ var mockFileData = GetMockFileDataForRead(throwIfNotExisting: false);
+ if (mockFileData == null || mockFileData.IsDirectory)
{
throw CommonExceptions.FileNotFound(path);
}
- return MockFileData.Contents.Length;
+ return mockFileData.Contents.Length;
}
}
@@ -382,5 +368,34 @@ public override string ToString()
{
return originalPath;
}
+
+ private MockFileData GetMockFileDataForRead(bool throwIfNotExisting = true)
+ {
+ if (refreshOnNextRead)
+ {
+ Refresh();
+ refreshOnNextRead = false;
+ }
+ var mockFileData = cachedMockFileData;
+ if (mockFileData == null)
+ {
+ if (throwIfNotExisting)
+ {
+ throw CommonExceptions.FileNotFound(path);
+ }
+ else
+ {
+ return null;
+ }
+ }
+ return mockFileData;
+ }
+
+ private MockFileData GetMockFileDataForWrite()
+ {
+ refreshOnNextRead = true;
+ return mockFileSystem.GetFile(path)
+ ?? throw CommonExceptions.FileNotFound(path);
+ }
}
}
diff --git a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryInfoTests.cs b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryInfoTests.cs
index b8fc34e15..7b894f755 100644
--- a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryInfoTests.cs
+++ b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryInfoTests.cs
@@ -393,5 +393,55 @@ public void MockDirectoryInfo_ToString_ShouldReturnDirectoryName(string director
// Assert
Assert.AreEqual(directoryPath, mockDirectoryInfo.ToString());
}
+
+ [Test]
+ public void MockDirectoryInfo_Exists_ShouldReturnCachedData()
+ {
+ // Arrange
+ var fileSystem = new MockFileSystem();
+ var path = XFS.Path(@"c:\abc");
+ var directoryInfo = fileSystem.DirectoryInfo.FromDirectoryName(path);
+
+ // Act
+ fileSystem.AddDirectory(path);
+
+ // Assert
+ Assert.IsFalse(directoryInfo.Exists);
+ }
+
+ [Test]
+ public void MockDirectoryInfo_Exists_ShouldUpdateCachedDataOnRefresh()
+ {
+ // Arrange
+ var fileSystem = new MockFileSystem();
+ var path = XFS.Path(@"c:\abc");
+ var directoryInfo = fileSystem.DirectoryInfo.FromDirectoryName(path);
+
+ // Act
+ fileSystem.AddDirectory(path);
+ directoryInfo.Refresh();
+
+ // Assert
+ Assert.IsTrue(directoryInfo.Exists);
+ }
+
+ [Test]
+ public void MockDirectoryInfo_LastAccessTime_ShouldReflectChangedValue()
+ {
+ // Arrange
+ var path = XFS.Path(@"c:\abc");
+ var fileSystem = new MockFileSystem(new Dictionary
+ {
+ { path, new MockDirectoryData() }
+ });
+ var directoryInfo = fileSystem.DirectoryInfo.FromDirectoryName(path);
+ var lastAccessTime = new DateTime(2022, 1, 8);
+
+ // Act
+ directoryInfo.LastAccessTime = lastAccessTime;
+
+ // Assert
+ Assert.AreEqual(lastAccessTime, directoryInfo.LastAccessTime);
+ }
}
}
\ No newline at end of file
diff --git a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileInfoTests.cs b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileInfoTests.cs
index 82ae5f0cb..440d2b7a7 100644
--- a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileInfoTests.cs
+++ b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileInfoTests.cs
@@ -718,5 +718,36 @@ public void MockFileInfo_Replace_ShouldThrowIfDestinationFileDoesNotExist()
Assert.Throws(() => fileInfo.Replace(path2, null));
}
+
+ [Test]
+ public void MockFileInfo_Exists_ShouldReturnCachedData()
+ {
+ // Arrange
+ var fileSystem = new MockFileSystem();
+ var path1 = XFS.Path(@"c:\temp\file1.txt");
+ var fileInfo = fileSystem.FileInfo.FromFileName(path1);
+
+ // Act
+ fileSystem.AddFile(path1, new MockFileData("1"));
+
+ // Assert
+ Assert.IsFalse(fileInfo.Exists);
+ }
+
+ [Test]
+ public void MockFileInfo_Exists_ShouldUpdateCachedDataOnRefresh()
+ {
+ // Arrange
+ var fileSystem = new MockFileSystem();
+ var path1 = XFS.Path(@"c:\temp\file1.txt");
+ var fileInfo = fileSystem.FileInfo.FromFileName(path1);
+
+ // Act
+ fileSystem.AddFile(path1, new MockFileData("1"));
+ fileInfo.Refresh();
+
+ // Assert
+ Assert.IsTrue(fileInfo.Exists);
+ }
}
}