在DUnitx中测试,Delphi模拟通过私有记录
我是DUnitx和Delphi Mocks的新手,请耐心等待。我能找到的关于这个话题的其他帖子只有3年了,没有得到回复 Delphi Rio 10.3。 视窗10 我想测试这个过程:在DUnitx中测试,Delphi模拟通过私有记录,delphi,testing,delphi-mocks,Delphi,Testing,Delphi Mocks,我是DUnitx和Delphi Mocks的新手,请耐心等待。我能找到的关于这个话题的其他帖子只有3年了,没有得到回复 Delphi Rio 10.3。 视窗10 我想测试这个过程: procedure TdmMariaDBConnection.Notify; var LViewModel : IPsViewModel; begin FMainViewModel.HandleCommands(FCommandRecord); for LViewModel in FObservers
procedure TdmMariaDBConnection.Notify;
var
LViewModel : IPsViewModel;
begin
FMainViewModel.HandleCommands(FCommandRecord);
for LViewModel in FObservers do
LViewModel.HandleCommands(FCommandRecord);
end;
接口和记录类型声明为:
IPsView = interface(IInvokable)
['{F5532762-09F8-42C4-9F9F-A8F7FF7FA0C6}']
procedure HandleCommands(const Value: TPsCommandRecord);
procedure AfterCreate;
procedure BeforeDestroy;
end;
IPsViewModel = interface(IInvokable)
['{322DAB08-6A7C-4B61-B656-BC5346ACFC14}']
procedure HandleCommands(const Value: TPsCommandRecord);
end;
IPsMainViewModel = interface(IInvokable)
['{98FFB416-6C22-492F-BC85-D9A1ECA667FE}']
procedure Attach(const observer: IPsView);
procedure Notify;
procedure LoadFrame(const Value: TPanel);
procedure LoadForm(const Value: integer);
procedure LoadModalForm(const Value: integer);
procedure HandleCommands(const Value: TPsCommandRecord);
procedure SetViewFactory(Value: IPsViewFactory);
property ViewFactory: IPsViewFactory write SetViewFactory;
end;
TPsCommandRecord = record
CommandType: integer;
CommandObject: TObject;
CommandMessage: TPsTaskDialogMessageRecord;
end;
我在受保护部分有通知程序
type
TdmMariaDBConnection = class(TDataModule, IPsModel)
procedure DataModuleDestroy(Sender: TObject);
procedure DataModuleCreate(Sender: TObject);
private
FObservers : TList<IPsViewModel>;
FMainViewModel : IPsMainViewModel;
FCommandRecord : TPsCommandRecord;
protected
procedure Notify;
….
end;
所以我可以调用受保护的方法。到目前为止,我所拥有的不起作用,因为我无法从TdmMariaDBConnection提供私有记录实例,现在只关注MainViewModel
procedure TTestModel_MariaDBConnection.NotifyCallsMainViewModelHandleCommands;
var
MVMMock : TMock<IPsMainViewModel>;
LCommandRecord : TPsCommandRecord;
begin
//Arrange
MVMMock := TMock<IPsMainViewModel>.Create;
MVMMock.Setup.Expect.Once.When.HandleCommands(LCommandRecord);
//Act
CUT.Attach(MVMMock);
CUT.Notify;
//Assert
try
MVMMock.Verify();
Assert.Pass();
except on E: EMockException do
Assert.Fail(E.Message);
end;
end;
测试甚至没有完成,我在TestInsight GUI中得到了一个不完整的圆圈,而不是希望的绿色检查
任何帮助都将不胜感激。这也是验证的正确用法吗?我只能找到这样的解释,即它在传递时不做任何事情,那么如何添加断言呢
提前谢谢
Gary在调用Verify时,设置模拟的方式将对传递的参数非常严格,并检查与指定设置的相等性 Delphi模拟中还有一个长期存在的问题,即记录参数没有正确地进行相等性比较(只有当参数的地址完全相同时,它们才相等-请参见
Delphi.Mocks.Helpers.pas中的SameValue
-我知道这个问题,因为我的代码是在我的许可下使用的-我不久前在Spring4D中编写了一个更好的版本,它也有mocking fwiw)。这就是为什么即使它不会与您添加的GetCommandRecord
一起在一个圆圈中运行,它也可能不会通过
我通常建议人们在使用mocks时(到目前为止,我为Delphi编写了两个mocking库)要尽可能地允许。幸运的是,Delphi mocks支持参数匹配器,允许您指定实际上您并不太关心所传递参数的确切值
也就是说,只需将设置更改为调用
MVMMock.Setup.Expect.Once.When.HandleCommands(It0.IsAny<TPsCommandRecord>);
MVMMock.Setup.Expect.one.When.handleCommand(It0.IsAny);
这告诉记录来自SUT的模拟调用的内部匹配器,满足预期的值并不重要
顺便说一句,由于与SameValue
bug类似的原因,使用It0.IsEqualTo(LCommandRecord)将无法工作
因为用于记录的比较器在内部调用了System.Generics.Defaults.Equals\u Binary
,它只对记录进行平面内存比较,对于任何引用类型都可能失败。谢谢,这就成功了。你会推荐使用Spring4D而不是Delphi Mocks吗?作为Spring4D的维护者,我有点偏见,但是Delphi Mocks最近很少受到关注(看起来是这样),而且我的mocking库中不存在一些问题(两个库中都存在一些问题,这是由于Delphi RTTI中的缺陷造成的)。它们的工作方式有点不同,因为Spring4D Mocks更受Moq的启发。我想说,尝试一下,然后决定您更喜欢哪个。
function TdmMariaDBConnection.GetCommandRecord: TPsCommandRecord;
begin
Result := FCommandRecord;
end;
MVMMock.Setup.Expect.Once.When.HandleCommands(CUT.GetCommandRecord);
MVMMock.Setup.Expect.Once.When.HandleCommands(It0.IsAny<TPsCommandRecord>);