Hello Uncle Bob
Thank you for your reply.
I've been trying to implement your suggestions, unfortunately I was only 50% successful.
For the first 2 functions I created a DataProvider class that returns StreamReader to the first function and a StreamWriter to the second. It also has the job of closing the streams.
This allowed me to mock the DataProvider class and have it write to a Hashtable(String fileName, byte[] contents) instead of the disk, using MemoryStreams. (I did not want to use ramdisks because from what I googled they require installation, and I cannot expect the client to do that in order to run the tests. Perhaps you know of a good library that does the job?)
As for the DataProvider class, since it is only creating and closing streams, I suppose the only tests needed are the ones to check if the methods are called.
This took care of testing the first half of the class.
As for the second part, I am still stumped. The last 2 methods look like this:
public void DownloadLink(DownloadDescriptor descriptor) {
String address = descriptor.URL;
WebClient client = new WebClient();
try {
Uri uri = new Uri(address);
client.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadLinkCompleted);
CreateTargetOutputDirectory(descriptor.TargetFileName);
client.DownloadFileAsync(uri, descriptor.TargetFileName, descriptor);
currentDownload = client;
} catch (Exception ex) {
descriptor.DownloadComplete = false;
AsyncCompletedEventArgs args = new AsyncCompletedEventArgs(ex, false, descriptor);
DownloadLinkCompleted(client, args);
}
}
private void DownloadLinkCompleted(Object sender, AsyncCompletedEventArgs e) {
DownloadDescriptor downloadDescriptor = (DownloadDescriptor)e.UserState;
String errorMessage = "";
if (e.Error != null)
errorMessage = e.Error.Message;
ioDelegate.DownloadCompleted(downloadDescriptor, errorMessage);
}
public void CancelCurrentDownload() {
if (currentDownload != null)
currentDownload.CancelAsync();
}
currentDownload is a class variable that holds the well... the current download and ioDelegate is the caller.
As you can see, all the DownloadLink and CancelCurrentDownload do is set up a WebClient and just call methods on it. If I create sockets and start a download from one of them, the WebClient will download to the actual disk, and not to my nice hashtable. So I see no way of mocking anything here. Wait...I just realized that puting the WebClient routines into the DataProvider class and just forwarding the download call to it might work. The DataProvider mock would just simulate the download to the hashtable, and the tests for these 2 methods would simply be to check if they are actually called. Is this correct?