题
一个数据库应用程序,目前,我正在工作上,储存各种设置的数据库。大多数的这些设置有来自某些业务规则,但也有一些其他的东西在那里。
该程序包含对象,具体做一个特定的任务,例如,某些复杂的计算。这些非UI对象单元的测试,但还需要获得大量的这些全球设置。我们已经实现这一权利,是通过给予的对象的性都充满了通过应用控制器在运行时间。测试时,我们创建的目的在于测试和填写的价值观进行测试(而不是从数据库)。
这一工作得更好,在任何情况下更多具有所有这些对象需要的一些全球性 设置 对象,当然有效使单元的测试不可能的:)缺点可以,你有时候需要设置一个属性,或者,你需要让那些属性'渗入子的对象。
所以一般的问题是:你怎么提供进入全球应用程序设置在项目中,而不需要为全球变量,同时仍然能够单元测试你的代码吗?这必须是一个问题已经解决了100倍...
(注:我不太多的一个有经验的程序员,因为你已经注意到;但是我喜欢学习!当然,我已经做了研究这个主题,但是我真的在寻找一些第一手经验)
解决方案
你可以使用马丁*本ServiceLocator模式。在php它可能看起来是这样的:
class ServiceLocator {
private static $soleInstance;
private $globalSettings;
public static function load($locator) {
self::$soleInstance = $locator;
}
public static function globalSettings() {
if (!isset(self::$soleInstance->globalSettings)) {
self::$soleInstance->setGlobalSettings(new GlobalSettings());
}
return self::$soleInstance->globalSettings;
}
}
你的生产码然后初始化服务定位器是这样的:
ServiceLocator::load(new ServiceLocator());
在你的测试码,你插入你的模拟设置这样的:
ServiceLocator s = new ServiceLocator();
s->setGlobalSettings(new MockGlobalSettings());
ServiceLocator::load(s);
这是个储存库对于单身人士可以交换为测试目的。
其他提示
我喜欢我的模型配置访问的服务定位的模式。这给了我一个单一点得到任何配置价值,我需要和把它应用程序之外在一个单独的图书馆,它可重复使用和可测试性。这里是一样的代码,我不知道该用什么语言使用的,但是我写的。
第一,我创建一个通用的类型我的ConfigurationItem.
public class ConfigurationItem<T>
{
private T item;
public ConfigurationItem(T item)
{
this.item = item;
}
public T GetValue()
{
return item;
}
}
然后我创建了一个类暴露了公共静只读的变量,用于配置的项目。在这里,我只是读取ConnectionStringSettings从config文件,该文件只是xml。当然更多的项目,可以读取的数值从任何来源。
public class ConfigurationItems
{
public static ConfigurationItem<ConnectionStringSettings> ConnectionSettings = new ConfigurationItem<ConnectionStringSettings>(RetrieveConnectionString());
private static ConnectionStringSettings RetrieveConnectionString()
{
// In .Net, we store our connection string in the application/web config file.
// We can access those values through the ConfigurationManager class.
return ConfigurationManager.ConnectionStrings[ConfigurationManager.AppSettings["ConnectionKey"]];
}
}
然后当我需要一个ConfigurationItem用,我呼吁它这样的:
ConfigurationItems.ConnectionSettings.GetValue();
它将返回我一个类型安全的价值,然后我就可以缓或做任何我想要的。
这里是一样的试验:
[TestFixture]
public class ConfigurationItemsTest
{
[Test]
public void ShouldBeAbleToAccessConnectionStringSettings()
{
ConnectionStringSettings item = ConfigurationItems.ConnectionSettings.GetValue();
Assert.IsNotNull(item);
}
}
希望这会有所帮助。
这通常是由一个ini文件或XML配置文件。然后你只有一类读设在之前的评价会显示.
.净具有这种建立在ConfigurationManager类,但它很容易实现的,只读文本的文件或载荷成DOM XML或者分析他们的代码。
具有的配置文件的数据库是确定的,但它不会把你绑来的数据库,并创建一个额外依赖于你的应用程序,ini/xml文件的解决。
我这样做:
public class MySettings
{
public static double Setting1
{ get { return SettingsCache.Instance.GetDouble("Setting1"); } }
public static string Setting2
{ get { return SettingsCache.Instance.GetString("Setting2"); } }
}
我把这个放在一个单独的基础设施模块中删除的任何问题圆形的相关性。
这样做我不依赖于任何特定的结构的方法,和有没有任何运行的破坏在我的应用程序的代码。