I would like to test a class that is using the method File.OpenRead() to obtain the content of a file. After reading the content of the file then it processes them. I have create an interface and a class that wraps the static OpenRead() method. But I encounter the problem that OpenRead() returns a FileStream and I have no idea how to "mock" the file stream.
Currently, I am creating a file just to create a FileStream... Of course, the tests are regularly failing with a IOException because the file is still in use...
Stripped Example: Class:
class FileProcessor
{
public FileProcessor(IFileWrap fileWrap) // fileWrap only redirects the calls to the static methods of File class
{ ... }
public void Process(string file)
{
var content = fileWrap.ReadAllLines(file);
// process content
}
}
And the test:
[TestClass]
public class FileProcessor_Test
{
[TestMethod]
Process_FileNotReadable_Exception()
{
File.WriteAllText(testFile, "something");
var fileWrapMock = new Mock<IFileWrap>();
FileProcessor dut = new FileProcessor(fileWrapMock.Object);
var actualException = AssertException.Throws<Exception>(() => dut.Process(testFile));
}
}
I would like to avoid creating an abstraction of FileStream, too.
I was hoping that I could create a MemoryStream and somehow use this as the input, but this would require to change the file wrapper and deviate from the actual File class.
Any input is appreciated :)
Edit:
The processing includes computing a MD5 checksum by calling ComputeHash() from the the class MD5.
Your original method is tightly coupled to the fact that it operates on a file. Don't do that. Make the method take a Stream, any stream. You can operate on a FileStream, or you can pass a MemoryStream for testing.
public void Process(string file)
Should be
public void Process(Stream stream)
If you want to, you could have a second method overload for convenience:
public void Process(string file)
{
using (var stream = new FileStream(file, FileMode.Open))
{
this.Process(stream);
}
}
That indeed cannot and should not be unit tested... it's .NET code handling external resources, at some point you have to trust the framework.
To address your edit: most Framework classes do something similar, for example the MD5 class has a ComputeHash method that works on a stream.
First of all, you don't need to unit test 'File' class as 'OpenRead' is a static method of 'File' class which you cannot decouple. It is not ideal to write a unit test against anything which has a dependency. In your case, you can mock 'IFileWrap' and create a mock method for 'ReadAllLines'. When unit test hits 'fileWrap.ReadAllLines(file)' method it will call the mock method instead of going to 'File.OpenRead()' method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With