One of the problems with static members or static classes is that you can't mock them for proper unit-testing. Instead of taking this fact for granted, let's demonstrate it. Assume that we have the following classes (please note, this is just an example, not production code or anything that I'll be proud of later on):
public class CsvDataExtractor { private string _documentPath; public CsvDataExtractor(string documentPath) { _documentPath = document; } public string ExtractFullName() { string content = CsvDocumentReader.GetContent(_documentPath); string fullName = // extract full name logic return fullName; }}[Test]public void ExtractFullName_DocumentHasFirstNameAndLastNameOnly(){ CsvDataExtractor extractor = new CsvDataExtractor("c:\test.csv"); string result = extractor.ExtractFullName(); Assert.AreEqual("ellenbogen", result);}
public interface IDocumentReader{ string GetContent(string documentPath);}public class CsvDataExtractor{ private string _documentPath; private IDocumentReader _reader; public CsvDataExtractor(IDocumentReader reader, string documentPath) { _documentPath = document; _reader = reader; } public string ExtractFullName() { string content = _reader.GetContent(_documentPath); string fullName = // extract full name logic return fullName; }}[Test]public void ExtractFullName_DocumentHasFirstNameAndLastNameOnly(){ DocumentReaderStub reader = new DocumentReaderStub(); reader.ContentToReturn = "oren,ellenbogen"; CsvDataExtractor extractor = new CsvDataExtractor(reader, "not important document path"); string result = extractor.ExtractFullName(); Assert.AreEqual("ellenbogen", result);}internal class DocumentReaderStub : IDocumentReader{ public string ContentToReturn; public string GetContent(string documentPath) { return ContentToReturn; }}
// the interface should look exactly like the static class we want to wrap !public interface IDocumentReader{ string GetContent(string documentPath);}// This class will simply delegate calls to the static classpublic class CsvDocumentReaderWrapper : IDocumentReader{ public string GetContent(string documentPath) { return CsvDocumentReader.GetContent(documentPath); // call the original static class }}
public class CsvDataExtractor{ private string _documentPath; public CsvDataExtractor(string documentPath) { _documentPath = document; } public string ExtractFullName() { string content = GetDocumentContent(); string fullName = // extract full name logic return fullName; } protected virtual string GetDocumentContent() { return CsvDocumentReader.GetContent(_documentPath); }}[Test]public void ExtractFullName_DocumentHasFirstNameAndLastNameOnly(){ TestableCsvDataExtractor extractor = new TestableCsvDataExtractor("not important document path"); extractor.ContentToReturn = "oren,ellenbogen"; string result = extractor.ExtractFullName(); Assert.AreEqual("ellenbogen", result);}public class TestableCsvDataExtractor : CsvDataExtractor{ public string ContentToReturn; public TestableCsvDataExtractor(string documentPath) : base(documentPath) { } protected virtual string GetDocumentContent() { return ContentToReturn; }}
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
© Copyright 2009, Oren Ellenbogen
<= Contact me via E-mail
newtelligence dasBlog 2.2.8279.16125