I use Visual Studio 2008 Professional automated tests. I have a function that writes to a file. I want to unit test the file writing function. I have read somewhere that I would have to mock a file somehow. I don't know how to do it. Can you help?
How to unit-test a method that downloads a page from the Internet?
views:
1099answers:
4If the method has to open the file stream itself, then that's hard to mock. However, if you can pass a stream into the method, and make it write to that, then you can pass in a MemoryStream instead. An alternative overload can take fewer parameters, open the file and pass a FileStream to the other method.
This way you don't get complete coverage (unless you write a test or two which really does hit the disk) but most of your logic is in fully tested code, within the method taking a Stream parameter.
It depends how close your code is to the nuts'n'bolts; for example, you could work in Stream
s instead, and pass a MemoryStream
to the code (and check the contents). You could just write to the file-system (in the temp area), check the contents and ditch it afterwards. Of if your code is a bit above the file system, you could write a mockable IFileSystem
interface with the high-level methods you need (like WriteAllBytes
/ WriteAllText
). It would be a pain to mock the streaming APIs, though.
For downloading from the internet (or pretending to)... you could (for example) write an IWebClient
interface with the functions you need (like DownloadString
, etc); mock it to return fixed content, and use something like WebClient
as the basis for an actual implementation. Of course, you'll need to test the actual implementation against real sites.
You don't actually want to make the call to write the file directly in your function but instead wrap the file I/O inside a class with an interface.
You can then use something like Rhino Mocks to create a mock class implementing the interface.
If the goal of your test is to test that the file is actually created, it is an integration test, and not a unit test.
If the goal it to test that the proper things are writen into the file, hide the file access behind an interface, and provide an in memory implementation.
The same is true for web page access.
interface IFileService
{
Stream CreateFile(string filename);
}
class InMemoryFileService : IFileService
{
private Dictionary<string, MemoryStream> files = new Dictionary<string, MemoryStream>();
public Stream CreateFile(string filename)
{
MemoryStream stream = new MemoryStream();
files.Add(filename, stream);
return stream;
}
public MemoryStream GetFile(string filename)
{
return files[filename];
}
}
Using GetFile, you can find what should be written to disk.