我还处于关于单元测试的学习阶段,特别是关于模拟(我正在使用PascalMock和DUnit框架).我现在偶然发现的一件事是,我找不到将测试类/接口的硬编码实现细节硬编码到我的单元测试中的方法,这只是感觉不对...
例如:我想测试一个实现非常简单的接口的类,用于读取和编写应用程序设置(基本上是名称/值对).呈现给消费者的界面完全不知道实际存储值的位置和方式(例如,注册表,INI文件,XML,数据库等).当然,访问层是由一个不同的类实现的,该类在构造时被注入到测试类中.我为这个访问层创建了一个模拟对象,现在我可以完全测试接口实现类,而无需实际读取或写入任何注册表/ INI文件/任何内容.
但是,为了确保模拟行为与被测试类访问时的真实行为完全相同,我的单元测试必须通过非常明确地定义预期的方法调用和测试类所期望的返回值来设置模拟对象.这意味着如果我必须更改访问层的接口或测试类使用该层的方式,我还必须更改内部使用该接口的类的单元测试,即使接口我实际上测试的类没有改变.这是我在使用模拟时必须要使用的东西,还是有更好的方法来设计避免这种情况的类依赖性?
我需要显示16x16像素图标以显示错误/警告/信息.不幸的是LoadIcon(0, IDI_*),LoadImage(0, OIC_*, IMAGE_ICON, 16, 16, LR_SHARED)我总是给我32x32版本的图标.
我读过ShGetStockIconInfo但是只能从Vista开始,我仍然需要支持XP.
有任何想法吗?
TImage如果重要的话,我正在使用Delphi 2010和一个组件.
将项目从Delphi 2007升级到Delphi 2009后,我收到了一个未知的内存泄漏,到目前为止我一直在尝试使用fastMM来跟踪它,这是fastMM堆栈跟踪报告:
A memory block has been leaked. The size is: 20
This block was allocated by thread 0x111C, and the stack trace (return addresses)
at the time was:
40339E [System.pas][System][@GetMem][3412] 534873 [crtl][_malloc]
56D1C4 [canex.cpp][MidasLib][DllGetDataSnapClassObject][3918]
56D316 [canex.cpp][MidasLib][DllGetDataSnapClassObject][3961]
56D5EE [canex.cpp][MidasLib][DllGetDataSnapClassObject][4085]
562D48 [DBCommon.pas][DBCommon][TFilterExpr.PutExprNode][1583]
408E46 [System.pas][System][DynArraySetLength][20464]
56D5EE [canex.cpp][MidasLib][DllGetDataSnapClassObject][4085]
408E92 [System.pas][System][@DynArraySetLength][20486]
528C1B [Forms.pas][Forms][TCustomForm.DoCreate][3260]
171A1A [GetRawStackTrace]
The block is currently used for an object of class: Unknown
The allocation number is: 302844
Run Code Online (Sandbox Code Playgroud)
有时我得到这个:
A memory block has been leaked. The size is: 20
This …Run Code Online (Sandbox Code Playgroud) 我在HTML帮助研讨会中创建了一个项目.当我打开帮助(/ chm)应用程序时,我可以看到目录.默认情况下,选择文件中的第一个条目,但是我看不到相应的页面数据,而是能够看到"此程序无法显示网页"(IE7中出现的默认错误消息).页面显示只有当我点击左侧的任何内容时.
有没有办法默认显示页面而不点击该条目?
谢谢Rupa
我刚刚开始使用Delphi Spring Framework,并想知道当前版本的DI容器是否允许将构造委托给工厂方法而不指定实现类型?
例如类似的东西:
GlobalContainer
.RegisterFactory<ISomeObject>(
function: ISomeObject
begin
Result := CreateComObject(CLASS_SomeObject) as ISomeObject;
end)
.Implements<ISomeObject> // could probably be implied from the above
.AsSingletonPerThread;
Run Code Online (Sandbox Code Playgroud)
如您所见,我的具体用例是COM对象的实例化.在这种情况下,实现我感兴趣的接口的类不是我的应用程序的一部分,但我仍然可以通过调用CreateComObject/ 来创建实例CoCreateInstance.但是,似乎我运气不好,因为Container中的注册似乎总是绑定到实际的实现类.
假设目前不可能这样做,那么你们的专家怎么解决这个问题呢?你会创建一个包装类或虚拟类,或者你只是将COM对象保留在DI容器之外并简单地通过它实例化它们CreateComObject?
目前阻碍我从单纯测试中获取热量的一个最大问题是我编写的代码中很大一部分在很大程度上依赖于来自不同来源的第三方COM对象,这些对象也倾向于相互交互(I'如果您需要知道,请使用多个帮助程序库为Microsoft Office编写加载项.
我知道我应该使用模拟对象但在这种情况下我究竟会怎么做呢?我可以看到,当我必须传递对已经存在的对象的引用时相对容易,但是我的一些例程本身实例化外部COM对象,然后有时将它们传递给来自不同库的其他外部COM对象.
这里最好的做法是什么?我是否应该让我的测试代码暂时更改注册表中的COM注册信息,以便测试的代码将实例化我的一个模拟对象?我应该注入修改后的类型库单位吗?有什么其他方法吗?
我会特别感谢Delphi的示例或工具,但同样对更一般的建议和更高级别的解释也同样满意.
谢谢,
奥利弗
我正在尝试编写如下所示的通用缓存属性访问器,但在尝试检查存储变量是否已包含值时遇到编译器错误:
function TMyClass.GetProp<T>(var ADataValue: T; const ARetriever: TFunc<T>): T;
begin
if ADataValue = Default(T) then // <-- compiler error on this line
ADataValue := ARetriever();
Result := ADataValue;
end;
Run Code Online (Sandbox Code Playgroud)
我得到的错误是"E2015运算符不适用于此操作数类型".
我是否必须约束T才能使这项工作?帮助文件说Default()除了泛型类型之外会接受任何东西.在我的情况,我用简单的类型,如内容大都String,Integer和TDateTime.
或者是否有其他库函数来执行此特定检查?
我正在使用Delphi 2009以防万一.
PS:以防万一我从代码中不清楚我正在尝试做什么:在我的情况下,由于各种原因确定实际属性值可能需要一段时间,有时甚至根本不需要它们.在正面但是值是常量所以我只想调用第一次访问属性时确定实际值的代码,然后将值存储在类字段中,下次访问该属性时返回缓存值直.这是我希望能够使用该代码的示例:
type
TMyClass = class
private
FSomeProp: String;
function GetSomeProp: String;
function GetProp<T>(var ADataValue: T; const ARetriever: TFunc<T>): T;
public
property SomeProp read GetSomeProp;
end;
function GetSomeProp: String;
begin
Result := GetProp<String>(FSomeProp,
function: String
begin
Result …Run Code Online (Sandbox Code Playgroud) 我目前正在尝试将我们的版本控制切换到Git(来自CVSNT).令人惊讶的是,这不是我遇到问题的分期性或临时区域的概念.但是,我很难解决AFAICT操作(如分支,合并和标记)始终应用于存储库级别而不是文件或目录级别的问题.
我们在不同的项目中重用了很多代码.我的工作区目前看起来像这样:
/Dev
/Libs
/LibA
/LibB
/LibC
/Project1
/Project2
/Project3
/WebDev
Run Code Online (Sandbox Code Playgroud)
现在,假设Project1依赖于LibA和LibB,Project2依赖于LibB和LibC,而Project3没有lib依赖.其中一些lib后来被编译成DLL(或BPL-我们的主要开发环境是Delphi),其他只是可重用代码的集合,它们逐个文件地包含在主项目中.
WebDev包含我们(主要是静态的)公司网站的代码,该网站还包含有关Project1,2,3的信息,因此可能必须与它们一起标记.
由于我在项目之间切换很多,我通常会同时检查所有这些,在必要时将lib目录即时更新到相应的项目分支.
我将如何在Git中对此进行建模,是否有理由坚持这种工作方式?我已经阅读了关于git子模块但是到目前为止我没有看到我将如何应用这里有几个原因:
据我所知,子模块总是会在各自的"超级项目"中检出.但是,我们发现使用Delphi管理(设计时)库代码的多个副本是皇家PITA,这是我们将所有库保存在单个项目树之外的公共目录下的原因之一.其他副本只能通过构建自动化进行检查,从不进行任何实际工作.
我真的不希望libs与项目"独立":如果我标记或分支其中一个项目,我总是想标记或分支各自的库.当我想回到主项目的特定标记版本时,我希望libs也可以恢复到该状态.如果可能,标记/分支/签出应始终在项目及其依赖项的单个步骤中发生.
我已经尝试将所有内容放在一个Git存储库中,其中库代码主要在主分支上进行管理,并且每个"项目"都在自己的分支上,但每当我尝试合并主服务器和项目分支之间的lib更改时,它就会拉动来自不相关的libs的所有文件,这根本不是我想要的......
你们有什么想法如何最好地解决这一切?我对所有的建议都持开放态度,包括我工作树的新布局.
如果有人能指出我关于子模块的实际动手教程(或者我需要完成的任何其他技术),那也很棒.
git version-control git-submodules version-control-migration
在 Office 2007 之前,插件通常会在主选项对话框(工具|选项)中添加标签页,用户可以在其中配置插件的设置。虽然这在 Office 2010 中基本上仍然有效,但它的实现方式似乎是一个向后兼容的离合器,类似于新功能区上的“COM-Addins”选项卡,其中按钮在以前的版本中会被放置在工具栏上:
为了进入加载项的选项页面,您现在必须转到文件|选项,然后切换到加载项页面并查找“加载项选项”按钮,单击它,然后选择相关的加载项选项卡。我发现很难相信事情应该是这样的,或者是这样吗?当然应该有某种方法可以将我的插件选项直接放在文件|选项对话框中吗?
在哪里可以找到描述插件开发人员最佳实践的文档,该文档解释了在 Office 2010 中放置插件选项页面的位置(以及如何放置)?
我正在尝试_TLB为Outlook 2003,2007和2010(以及其他OLE服务器)生成类似于与Delphi for Outlook 2000和2002捆绑的导入单元.但是,我无法让类型库导入器也生成用于从捆绑单元中的OLE服务器捕获事件的代码.到"生成组件封装"选项仅会为直接实例化的服务器,而不是那些只通过像其他对象的方法返回的对象包装TInspector,TExplorer等等.
我当然可以自己创建事件处理代码,但这将是非常繁琐的工作.
有没有人知道Delphi 2010(tlibimp.exe)中包含的导入程序是否可以调整以生成该代码?我真的怀疑Borland在手工创建现有设备Outlook2000.pas和OutlookXP.pas单元的那一天......
是否有任何其他工具可以做到这一点?
delphi ×6
com ×2
mocking ×2
unit-testing ×2
add-in ×1
caching ×1
chm ×1
delphi-2009 ×1
dunit ×1
events ×1
fastmm ×1
generics ×1
git ×1
import ×1
loadimage ×1
memory-leaks ×1
ms-office ×1
office-2010 ×1
ole ×1
oop ×1
options ×1
pascalmock ×1
spring4d ×1
timage ×1
typelib ×1