Closed romainf-ubi closed 1 month ago
There is no built-in way to manipulate how the name of the created subdirectory is created and changing the signature is out of the question, as the maxime of this project is to map the the public interface of the .NET System.IO API as close as possible. However, maybe you could work around this issue as in the following example:
[Fact]
public void GetCreatedTempSubdirectory()
{
var fileSystem = new MockFileSystem();
// void Execute()
var tempDir = fileSystem.Directory.CreateTempSubdirectory();
fileSystem.File.Create(fileSystem.Path.Join(tempDir.FullName, "file.txt"));
var result = fileSystem.Directory.GetDirectories(
fileSystem.Path.GetTempPath()).Single();
result.Should().Be(tempDir.FullName);
}
As the MockFileSystem
starts with an empty temporary directory, your generated directory will be the only directory in the temp path and it should not be hard to get its path (or file name) in the test.
Would this work for you, @romainf-ubi ?
Thanks for your quick answer @vbreuss!
Don't worry, I fully understand that you don't want to change the signature of the system methods, and rest assure that it's not what I'm proposing 😄 Actually I'm more explaining my issue than proposing anything, but I hope that this discussion may lead to a nice solution.
My issue is only on the mock/fake testing side, where I need to know where the next temporary directory will be created before calling the method I'm testing (i.e. sut.Execute()
).
I'll test your solution and I'll get back to you asap.
So it took me some time to understand how your workaround would fit my requirements, but I eventually got to change my mind around and find a proper solution!
The issue was that I was just thinking about mocking services (and not about faking them). So, in the mocking mindset, I wanted to prepare all the dependencies calls so that the calling method can run. But in the faking mindset, what I really needed was to fake creating the file when the dependent service required it.
So, in more concrete terms, I mocked the dependent service so that it will create a fake file when requested, like so:
public TestExecute()
{
// Arrange
var mockFileSystem = new MockFileSystem();
var downloadServiceMock = new Mock<IDownloadService>();
var sut = new Job(mockFileSystem.Object, downloadServiceMock.Object);
// Create the fake file when DownloadFileAsync() is called.
downloadServiceMock
.Setup(x => x.DownloadFileAsync(It.IsAny<Uri>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Callback((Uri _, string filePath, CancellationToken _) => fakeFileSystem.File.Create(filePath));
// Act
sut.Execute();
// Assert
downloadServiceMock.Verify(
x => x.DownloadFileAsync(It.IsAny<Uri>(), It.IsAny<string>(), It.IsAny<CancellationToken>()),
Times.Once());
}
In the end, I don't care about the temporary directory path as I only care that the whole Execute()
method ran as expected.
I'll close this issue, thanks for the help, and great work on this project, it really works well!
I am glad you found a solution 👍
Is your feature request related to a problem? Please describe. I can't mock methods that depends on
Directory.CreateTempSubdirectory()
.Describe the solution you'd like I'm fairly new using this package, but the idea would be to predictably know what the next calls to
CreateTempSubdirectory()
will return.Describe alternatives you've considered Instead of creating the temporary directory within the method, I could pass it as a parameter. The issue is that the method implements an interface that I can't modify to add the new parameter. I could add a property to the class, but then the dependency injection model will become weird as not everything will be set by the constructor.
Maybe there's a way to solve this by combining
MockFileSystem
andMock<IFileSystem>
?Additional context Imagine this class (I can't change
Execute
signature):It's possible that I'm doing it wrong, so if you have any insights, I'd be glad to hear them 😉