你在這裏失蹤的是控制反轉。舉例來說,你可以介紹依賴注入的原則,爲您的代碼:
public interface IXmlDataProviderFactory
{
XmlDataProvider Create(string fileName);
}
public class LocalizationData
{
private IXmlDataProviderFactory factory;
public LocalizationData(IXmlDataProviderFactory factory)
{
this.factory = factory;
}
private bool IsValidFileName(string fileName)
{
return fileName.ToLower().EndsWith("xml");
}
public XmlDataProvider LoadFile(string fileName)
{
if (IsValidFileName(fileName))
{
XmlDataProvider provider = this.factory.Create(fileName);
provider.IsAsynchronous = false;
return provider;
}
return null;
}
}
在創建XmlDataProvider
上面的代碼抽離使用IXmlDataProviderFactory
接口。該接口的實現可以在LocalizationData的構造函數中提供。現在,您可以編寫單元測試如下:
[Test]
public void LoadFile_DataLoaded_Succefully()
{
// Arrange
var expectedProvider = new XmlDataProvider();
string validFileName = CreateValidFileName();
var data = CreateNewLocalizationData(expectedProvider);
// Act
var actualProvider = data.LoadFile(validFileName);
// Assert
Assert.AreEqual(expectedProvider, actualProvider);
}
private static LocalizationData CreateNewLocalizationData(
XmlDataProvider expectedProvider)
{
return new LocalizationData(FakeXmlDataProviderFactory()
{
ProviderToReturn = expectedProvider
});
}
private static string CreateValidFileName()
{
return "d:/azeri.xml";
}
的FakeXmlDataProviderFactory
看起來是這樣的:
class FakeXmlDataProviderFactory : IXmlDataProviderFactory
{
public XmlDataProvider ProviderToReturn { get; set; }
public XmlDataProvider Create(string fileName)
{
return this.ProviderToReturn;
}
}
現在在測試環境中,你可以(並且可能應該)總是手動創建測試類。但是,您希望將工具方法中的創建抽象出來,以防止在被測試的類更改時不得不更改許多測試。
但是,在您的生產環境中,手動創建類時很快就會變得非常麻煩。特別是當它包含很多依賴關係時。這是IoC/DI框架的亮點。他們可以幫助你。舉例來說,當你想在你的產品代碼使用LocalizationData
,你可能會這樣寫代碼:
var localizer = ServiceLocator.Current.GetInstance<LocalizationData>();
var data = data.LoadFile(fileName);
請注意,我使用的是Common Service Locator來作爲例子。
該框架將負責爲您創建該實例。然而,使用這樣的依賴注入框架,您將不得不讓框架知道您的應用程序需要哪些「服務」。舉例來說,當我使用Simple Service Locator圖書館爲例(無恥插頭就是),你的配置可能是這樣的:
var container = new SimpleServiceLocator();
container.RegisterSingle<IXmlDataProviderFactory>(
new ProductionXmlDataProviderFactory());
ServiceLocator.SetLocatorProvider(() => container);
此代碼通常會在應用程序的啓動路徑。當然,唯一缺少的難題是實際的ProductionXmlDataProviderFactory
班。下面是它:
class ProductionXmlDataProviderFactory : IXmlDataProviderFactory
{
public XmlDataProvider Create(string fileName)
{
return new XmlDataProvider
{
Source = new Uri(fileName, UriKind.Absolute)
};
}
}
請也沒有,你可能不希望新的你LocalizationData
在生產自己的代碼,因爲這個類可能是使用依賴於這種類型的其他類。你通常會做的是要求框架爲你創建最高級的類(例如實現完整用例的命令)並執行它。
我希望這會有所幫助。
我認爲一些假冒的對象必須是使用替代XmlDataProvider – Polaris 2010-09-09 14:48:28
您可能會更好上更爲複雜,easer代碼花費你的時間去測試。這樣的事情可能會被系統級別的測試所覆蓋。 – 2010-09-09 15:02:44
不要忘記標記您最喜歡的答案;-) – Steven 2010-11-21 16:43:07