【问题标题】:Test in DUnitx with Delphi-Mocks passing private record使用 Delphi-Mocks 通过私有记录在 DUnitx 中进行测试
【发布时间】:2020-01-23 21:14:19
【问题描述】:

我是 DUnitx 和 Delphi-Mocks 的新手,所以请耐心等待。我能找到的关于这个主题的唯一其他帖子是 3 岁且没有回答。 Returning records in Delphi-Mocks

德尔福 Rio 10.3。 视窗 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 GUI 中得到一个不完整的圆圈,而不是希望的绿色检查。

任何帮助将不胜感激。这也是验证的正确用法吗?我只能找到通过时什么都不做的解释,那么如何添加Assert?

提前致谢 加里

【问题讨论】:

    标签: delphi testing delphi-mocks


    【解决方案1】:

    您设置模拟的方式将非常严格地传递参数并在调用验证时检查与指定设置的相等性。

    Delphi Mocks 中还有一个长期存在的问题,即记录参数没有正确比较是否相等(它们仅在地址完全相同的参数时相等 - 请参阅 Delphi.Mocks.Helpers.pas 中的 SameValue - 我知道这个问题是因为这是我的代码在我的许可下使用 - 我写了一个更好的版本,不久前在 Spring4D 中使用,它也有模拟 fwiw)。这就是为什么即使它不会与您添加的GetCommandRecord 循环运行,它也可能不会通过。

    在使用模拟时,我通常建议人们做的事情(到目前为止我为 Delphi 编写了 2 个模拟库)是尽可能宽容。幸运的是,Delphi Mocks 支持参数匹配器,让您可以指定实际上您并不关心传递的参数的确切值。

    话虽如此,只需将您的设置更改为调用

    MVMMock.Setup.Expect.Once.When.HandleCommands(It0.IsAny<TPsCommandRecord>);
    

    这告诉内部匹配器记录从 SUT 对模拟的调用,无论哪个值满足期望都没有关系。

    顺便说一句,由于与SameValue 错误类似的原因,它无法使用It0.IsEqualTo(LCommandRecord),因为用于记录的比较器内部调用System.Generics.Defaults.Equals_Binary,它只是对可能失败的记录进行平面内存比较任何引用类型。

    【讨论】:

    • 谢谢你,成功了。你会推荐在 Delphi-Mocks 上使用 Spring4D 吗?
    • 作为 Spring4D 的维护者,我有点偏颇——但 Delphi-Mocks 最近很少受到关注(看起来),而且我的模拟库中不存在一些问题(有些在两者中都有这是由 Delphi RTTI 的缺陷引起的)。它们的工作方式有点不同,因为 Spring4D 模拟更受 Moq 的启发。我会说试试看,然后决定你更喜欢哪个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 2023-04-01
    • 2012-03-10
    相关资源
    最近更新 更多