簡體   English   中英

在 DUnitx 中使用 Delphi-Mocks 傳遞私有記錄進行測試

[英]Test in DUnitx with Delphi-Mocks passing private record

我是 DUnitx 和 Delphi-Mocks 的新手,所以請耐心等待。 我能找到的關於這個主題的唯一其他帖子是 3 年前的,而且沒有回答。 在 Delphi-Mocks 中返回記錄

德爾福里約熱內盧 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 中得到一個不完整的圓圈,而不是希望的綠色檢查。

任何幫助,將不勝感激。 這也是 Verify 的正確用法嗎? 只能找到pass的時候什么都不做的解釋,那怎么加Assert呢?

在此先感謝加里

您設置模擬的方式將對傳遞的參數非常嚴格,並在調用 Verify 時檢查指定設置是否相等。

Delphi Mocks 中還有一個長期存在的問題,即記錄參數未正確比較是否相等(它們僅在參數位於完全相同的地址時才相等 - 請參閱SameValue中的Delphi.Mocks.Helpers.pas - 我知道這個問題是因為它我的代碼是在我的許可下使用的嗎——我前段時間寫了一個更好的版本,在 Spring4D 中使用,它也有 mocking 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 ,它只是對記錄進行平面內存比較,這可能任何引用類型都失敗。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM