Unit Test and Mock File methods – Guidelines
Today in this article on best practices, we shall see how to Unit Test and Mock File methods. We shall see a very simple approach of mocking and achieving good code coverage for the code using the file-based method like File.Exist() or File.Open methods.
We shall achieve this without using any mocking library or NuGet package or external component.
This approach is simple because we will be using the Interface approach concept and making sure we write test cases only for code that we have written and every other dependency is mocked properly.
In the last article, we learned the best practices for Unit testing where we saw we mock everything which doesn’t own.
Today in this article, we will cover below aspects,
Below I have a sample method that had a direct dependency on the File methods which we will see how to mock it as shown below,
Create IFileAccessor Interface
Crete IFileAccessor Interface Wrapper interface for the File method,
We have created this interface for adding a wrapper method that corresponds to the File.Exist() or File.Open() and WriteAllBytes legacy methods.
public interface IFileAccessor
{
bool Exists(string path);
FileStream Open(string path, FileMode mode, FileAccess access);
void WriteAllBytes(string path, byte[] bytes);
}
Implementation for IFileAccessor interfaces as below. Here we have created wrapper methods around File specific methods which we are currently using in the logic.
Please extend this interface for additional methods as required.
public class FileAccessor : IFileAccessor
{
public bool Exists(string filePath)
{
return File.Exists(filePath);
}
public FileStream Open(string filePath, FileMode mode, FileAccess access)
{
return File.Open(filePath, mode, access);
}
public void WriteAllBytes(string path, byte[] bytes)
{
File.WriteAllBytes(path, bytes);
}
}
Usig File Interface and Refactoring the Code
Effective Mocking requires you to follow interface-based implementation for better testable code.
Below we are injecting File Interface through constructor Injection.
Example – Mocking File.Exist method
Mock for File.Exist method can be written as below,
var mockFile = new Mock<IFileAccessor>(); //Prapare mock for File.Exist method mockFile.Setup(x => x.Exists(testFilePath)).Returns(true);
Example – Mocking File.Open method
Mock for File.Open method can be written as below,
//Prapare mock for File.Open method FileStream fsDummy = new FileStream("file-input-thecodebuzz.txt", FileMode.Open, FileAccess.Read); mockFile.Setup(x => x.Open(testFilePath, FileMode.Open,FileAccess.Read)).Returns(fsDummy );
In the above mocking, I have created a Filestream object using a mock file which I have placed as a test data file in the project location.
Above mock for File.Open method returns the dummy FileStreams object i.e fsDummy every time this method is called while unit testing the code.
Example – Mocking File.WriteAllBytes method
Mock for File.WriteAllBytes can be written as below,
//Prapare mock for File.WriteAllBytes method BufferedStream bs = new BufferedStream(fs); bs.Read(buffer, 0, fileSize); mockFile.Setup(x => x.WriteAllBytes(testFilePath, buffer));
Please see below the updated method after refactoring,
With the above mocking, one can test all possible unit test scenarios which were not possible initially.
I was able to test the below scenarios,
- File Path is empty or Null
- File Path is Invalid
- FilePath is valid and no of chunk files created are correct or not
- File staus is returned correctly
References:
Do you have any comments or ideas or any better suggestions to share?
Please sound off your comments below.
Happy Coding !!
Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.