利用Stub來打破關連性 (3)
Source: The art of unit testing with examples in .NET, Roy Osherove
http://www.amazon.com/Art-Unit-Testing-Examples-Net/dp/1933988274/ref=sr_1_1?ie=UTF8&s=books&qid=1267086529&sr=1-1
Chapter 3 Using stubs to break dependencies
接下來作者提出另一種作法, 使用factory paatern. 這樣做的好處是
(1) 你的受測程式便不用管FileExtension Manager是怎樣產生, 或是要用哪一個
(2) 每個class只有單一責任(SRP), LogAnalyzer只負責log, FileExtensionManager只負責怎麼驗證檔案, Factory則負責產生FileExtensionManager的object.
所以會讓程式更簡單, 可讀性更高, 責任更清楚, 將來更容易修改和維護.
方法 3. Factory pattern
// 受測程式
public class LogAnalyzer {
private IExtensionManager manager;
// 設定指向真的File Extension Manager
public LogAnalyzer() {
// 利用factory pattern來決定真正的Extension Manager
manager = ExtensionManagerFactory.Create();
}
public bool IsValidLogFileName(string fileName) {
return manager.IsValid(fileName);
}
}
[TestFixture]
public class LogAnnalyzerTests {
[Test]
public void IsValidFileName_NameShorterThan6() {
// 設定stub的內容
StubExtensionManager myFakeManager =
new StubExtensionManager();
myFakeManager.ShouldExtensionBeValid = true;
// 要做測試才將stub object放到factory object中
ExtensionManagerFactory.SetManager(myFakeManager);
LogAnalyzer log = new LogAnalyzer();
// 進行測試
bool result = log.IsValidLogFileName( "short.ext" );
// 檢查測試結果
Assert.IsFalse( result, "File name with less than 5 chars should have failed the method." );
}
// File Extension Manager的stub
internal class StubExtensionManager : IExtensionManager {
public bool ShouldExtensionBeValid;
public bool IsValid(string fileName) {
//實作僅供測試使用的功能
return ShouldExtensionBeValid;
}
}
}
// Factory pattern的實作
class ExtensionManagerFactory {
private IExtensionManager customManager = null;
public IExtensionManager Create() {
if (customManager != null )
return customManager;
// 沒有特殊狀況時, 預設就傳為真正的Extension manager
return new FileExtensionManager();
}
public void SetManager(IExtensionManager mgr) {
customManager = mgr;
}
}