Repository navigation
Added two constructors to MockFileData to allow for lazy loading of t… #144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,163 @@ | ||
| using System.Linq; | ||
| using NUnit.Framework; | ||
|
|
||
| namespace System.IO.Abstractions.TestingHelpers.Tests | ||
| { | ||
| [TestFixture] | ||
| public class MockFileDataLazyLoadContentTests | ||
| { | ||
| [Test] | ||
| public void MockFileData_AcceptsFuncAndReturnsContents() | ||
| { | ||
| var contents = Enumerable.Range(0, 100).Select(_ => (byte)_).ToArray(); | ||
| var x = new MockFileData(() => contents); | ||
| Assert.AreEqual(x.Contents, contents); | ||
| } | ||
|
|
||
| [Test] | ||
| public void MockFileData_LazyLoadFuncIsCalledOnDemand() | ||
| { | ||
| var contents = Enumerable.Range(19, 42).Select(_ => (byte)_).ToArray(); | ||
| var lazyLoadFuncHasBeenCalled = false; | ||
| var x = new MockFileData(() => | ||
| { | ||
| lazyLoadFuncHasBeenCalled = true; | ||
| return contents; | ||
| }); | ||
| Assert.IsFalse(lazyLoadFuncHasBeenCalled); | ||
| Assert.AreEqual(x.Contents, contents); | ||
| Assert.IsTrue(lazyLoadFuncHasBeenCalled); | ||
| } | ||
|
|
||
| [Test] | ||
| public void MockFileData_FuncConstructorThrowsOnNullArgument() | ||
| { | ||
| Assert.Throws<ArgumentNullException>(() => new MockFileData((Func<byte[]>)null)); | ||
| } | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd suggest an additional test case that verifies that the callback is not called multiple times. |
||
| } | ||
|
|
||
| [TestFixture] | ||
| public class MockFileDataLazyLoadAndDirectoryBrowsing | ||
| { | ||
| private class ContentCalledException : Exception | ||
| { | ||
| public ContentCalledException() : base("Content was called") | ||
| { | ||
| } | ||
| } | ||
|
|
||
| private IFileSystem fileSystem; | ||
|
|
||
| [SetUp] | ||
| public void SetUp() | ||
| { | ||
| var mockFileData = new MockFileData(() => | ||
| { | ||
| throw new ContentCalledException(); | ||
| }); | ||
| fileSystem = new MockFileSystem(); | ||
| ((MockFileSystem)fileSystem).AddFile(@"b:\thefile.useless", mockFileData); | ||
| } | ||
|
|
||
| [Test] | ||
| public void TestThatFileExist() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the main purpose of this test of to verify that the callback does not get invoked when checking whether the file exists. This assertion should be visible in the test body. |
||
| { | ||
| Assert.IsTrue(fileSystem.File.Exists(@"b:\thefile.useless")); | ||
| } | ||
|
|
||
| [Test] | ||
| public void TestThatDirectoryGetFilesDoesNotLoadContent() | ||
| { | ||
| Assert.AreEqual(1, fileSystem.Directory.GetFiles(@"B:\").Length); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above, I'd like to see the assertion here |
||
| } | ||
|
|
||
| [Test] | ||
| public void TestThatDirectoryInfoGetFilesDoesNotLoadContent() | ||
| { | ||
| Assert.AreEqual(1, fileSystem.DirectoryInfo.FromDirectoryName(@"B:\").GetFiles().Length); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above, I'd like to see the assertion here |
||
| } | ||
|
|
||
| [Test] | ||
| public void TestThatContentIsBeingUsedOnDemandWhenTheFileSizeIsRetrievedThruFileInfoObject() | ||
| { | ||
| var file = fileSystem.DirectoryInfo.FromDirectoryName(@"B:\").GetFiles().Single(); | ||
| long fileLength = -1; | ||
| Assert.Throws(typeof(ContentCalledException), () => fileLength = file.Length); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO asserting on
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why use an exception here instead of doing what you do in |
||
| Assert.AreEqual(-1, fileLength); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| [TestFixture] | ||
| public class MockFileDataInsertFileInfoObjectTests | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See comment below, let's move this to a separate PR |
||
| { | ||
| private IFileSystem destinationFileSystem; | ||
| private FileInfoBase destinationFileInfo; | ||
|
|
||
| private const string sourceFileName = @"a:\c.bin"; | ||
| private const string destinationFileName = @"b:\c\d.bin"; | ||
| private readonly byte[] fileContent = Enumerable.Range(3, 14).Select(_ => (byte)_).ToArray(); | ||
| private const FileAttributes attributes = FileAttributes.Hidden; | ||
| private readonly DateTime dateCreated = DateTime.Now.AddHours(-3); | ||
| private readonly DateTime dateLastWritten = DateTime.Now.AddHours(-2); | ||
| private readonly DateTime dateLastAccessed = DateTime.Now.AddHours(-1); | ||
|
|
||
| [TestFixtureSetUp] | ||
| public void MockFileData_AcceptsFuncAndReturnsContents() | ||
| { | ||
| // create a file in a source file system | ||
| var sourceFileSystem = new MockFileSystem(); | ||
| sourceFileSystem.File.WriteAllBytes(sourceFileName, fileContent); | ||
| sourceFileSystem.File.SetAttributes(sourceFileName, attributes); | ||
| sourceFileSystem.File.SetCreationTime(sourceFileName, dateCreated); | ||
| sourceFileSystem.File.SetLastWriteTime(sourceFileName, dateLastWritten); | ||
| sourceFileSystem.File.SetLastAccessTime(sourceFileName, dateLastAccessed); | ||
| var sourceFile = sourceFileSystem.DirectoryInfo.FromDirectoryName(Path.GetDirectoryName(sourceFileName)).GetFiles().Single(); | ||
|
|
||
| // create a new destination file system and copy the source file there | ||
| var dfs = new MockFileSystem(); | ||
| dfs.AddFile(destinationFileName, new MockFileData(sourceFileSystem, sourceFile)); | ||
| destinationFileInfo = dfs.DirectoryInfo.FromDirectoryName(Path.GetDirectoryName(destinationFileName)).GetFiles().Single(); | ||
| destinationFileSystem = dfs; | ||
| } | ||
|
|
||
| [Test] | ||
| public void TestThatFileHasRightName() | ||
| { | ||
| Assert.AreEqual(destinationFileName, destinationFileInfo.FullName); | ||
| } | ||
|
|
||
| [Test] | ||
| public void TestThatFileHasRightContent() | ||
| { | ||
| Assert.AreEqual(fileContent, destinationFileSystem.File.ReadAllBytes(destinationFileInfo.FullName)); | ||
| } | ||
|
|
||
| [Test] | ||
| public void TestThatFileHasRightAttributes() | ||
| { | ||
| Assert.AreEqual(attributes, destinationFileInfo.Attributes); | ||
| } | ||
|
|
||
| [Test] | ||
| public void TestThatFileHasRightCreationTime() | ||
| { | ||
| Assert.AreEqual(dateCreated, destinationFileInfo.CreationTime); | ||
| } | ||
|
|
||
| [Test] | ||
| public void TestThatFileHasRightWriteTime() | ||
| { | ||
| Assert.AreEqual(dateLastWritten, destinationFileInfo.LastWriteTime); | ||
| } | ||
|
|
||
| [Test] | ||
| public void TestThatFileHasRightAccessTime() | ||
| { | ||
| Assert.AreEqual(dateLastAccessed, destinationFileInfo.LastAccessTime); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,7 @@ public class MockFileData | |
| /// The actual contents of the file. | ||
| /// </summary> | ||
| private byte[] contents; | ||
| private readonly Func<byte[]> lazyLoadContent; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: What about calling this |
||
|
|
||
| /// <summary> | ||
| /// The date and time the <see cref="MockFileData"/> was created. | ||
|
|
@@ -97,11 +98,47 @@ public MockFileData(byte[] contents) | |
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the byte contents of the <see cref="MockFileData"/>. | ||
| /// Allows insertion of a file where the content is lazy loaded through a Func. | ||
| /// </summary> | ||
| /// <param name="lazyLoadContent">Func to return the file's content the first time it is requested.</param> | ||
| public MockFileData(Func<byte[]> lazyLoadContent) | ||
| { | ||
| if (lazyLoadContent == null) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about |
||
| { | ||
| throw new ArgumentNullException("lazyLoadContent"); | ||
| } | ||
| this.lazyLoadContent = lazyLoadContent; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Allows insertion of a FileSystemInfoBase object into a new file system. Attributes and time stamps | ||
| /// are copied, and the content will be lazy loaded the first time it is touched. | ||
| /// </summary> | ||
| /// <param name="fileSystem">The source file system where the file info originates</param> | ||
| /// <param name="fileInfo">The source file to be copied</param> | ||
| public MockFileData(IFileSystem fileSystem, FileSystemInfoBase fileInfo) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we discuss this separately? I like the lazy loading feature but I'm not sure this new constructor has to be here (instead of in user code).
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, it's closing in on three years since I wrote this, and I realize I have forgotten all about it. :-( 1) What do you propose we should do instead? 2) would it be easier to entirely drop this PR and that I create a new one from the current master, with your suggested changes? |
||
| { | ||
| if (fileSystem == null) | ||
| { | ||
| throw new ArgumentNullException("fileSystem"); | ||
| } | ||
| if (fileInfo == null) | ||
| { | ||
| throw new ArgumentNullException("fileInfo"); | ||
| } | ||
| creationTime = fileInfo.CreationTime; | ||
| lastAccessTime = fileInfo.LastAccessTime; | ||
| lastWriteTime = fileInfo.LastWriteTime; | ||
| attributes = fileInfo.Attributes; | ||
| lazyLoadContent = () => fileSystem.File.ReadAllBytes(fileInfo.FullName); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the byte contents of the <see cref="MockFileData"/>. | ||
| /// </summary> | ||
| public byte[] Contents | ||
| { | ||
| get { return contents; } | ||
| get { return contents ?? (contents = lazyLoadContent()); } | ||
| set { contents = value; } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't really matter, but what is the value of this ceremony when all you need is some byte array? Just do something like
var contents = new byte[] { 1, 2, 3 }.