我是DUnitx和Delphi的新手,所以请耐心等待。我能找到的关于这个话题的另一个帖子是3年前的,没有人回答。Returning records in Delphi-Mocks
Delphi rio10.3。Windows 10
我想测试一下这个过程:
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;在我的测试项目中,我有一个派生类
TTestabledmMariaDBConnection = class(TdmMariaDBConnection)
end;
var
CUT : TTestabledmMariaDBConnection;
procedure TTestModel_MariaDBConnection.Setup;
begin
CUT := TTestabledmMariaDBConnection.Create(nil);
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;显然,添加LCommandRecord是错误的,我添加它们只是为了编译它。我需要(我认为)设置中测试类的记录实例。我试着添加一个函数来获得它,但它也不起作用。
function TdmMariaDBConnection.GetCommandRecord: TPsCommandRecord;
begin
Result := FCommandRecord;
end;
MVMMock.Setup.Expect.Once.When.HandleCommands(CUT.GetCommandRecord);测试甚至还没有完成,我在TestInsight图形用户界面中得到了一个不完整的圆圈,而不是希望的绿色检查。
任何帮助都将不胜感激。另外,这是Verify的正确用法吗?我只能找到传递时没有作用的解释,那么如何添加断言呢?
先谢谢你,加里
发布于 2020-01-25 01:09:14
在设置mock的方式中,它将非常严格地限制传递的参数,并在调用Verify时检查是否与指定的设置相等。
在Delphi Mock中也有一个长期存在的问题,即记录参数没有正确地进行相等比较(它们只有在完全相同的地址时才相等-参见Delphi.Mocks.Helpers.pas中的SameValue -我知道这个问题,因为它是我的代码在我的许可下使用-不久前我写了一个更好的版本在Spring4D中使用,它也有mocking fwiw)。这就是为什么即使它不能在你添加的GetCommandRecord中循环运行,它也可能不会通过。
我通常建议人们在使用mocks时要尽可能宽松(到目前为止,我为Delphi写了两个mocking库)。幸运的是,Delphi Mocks支持参数匹配器,该参数匹配器允许您指定实际上您并不太关心传递的参数的精确值。
也就是说,只需将设置更改为调用
MVMMock.Setup.Expect.Once.When.HandleCommands(It0.IsAny<TPsCommandRecord>);这告诉记录来自SUT的mock调用的内部匹配器,满足期望值的值是什么并不重要。
顺便说一句,由于与SameValue错误类似的原因,它不能使用It0.IsEqualTo(LCommandRecord),因为用于记录的比较器在内部调用System.Generics.Defaults.Equals_Binary,它只是对记录进行平面内存比较,这对于任何引用类型都可能失败。
https://stackoverflow.com/questions/59887147
复制相似问题