Тестирование в DUnitx с Delphi-Mocks с прохождением частной записи
Я новичок в DUnitx и Delphi-Mocks, поэтому проявите терпение. Единственное сообщение по этой теме, которое я смог найти, было написано 3 года назад, и на него нет ответа. Возврат записей в Delphi-Mocks
Delphi Rio 10.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 вместо ожидаемой проверки Green.
Любая помощь будет оценена. Также правильно ли это использовать Verify? Я могу найти только объяснение, что он ничего не делает при прохождении, так как добавить Assert?
Заранее спасибо Гэри
1 ответ
То, как вы настраиваете макет, будет очень строгим в отношении передаваемых параметров и проверяет соответствие указанной настройке при вызове Verify.
В Delphi Mocks также существует давняя проблема, связанная с тем, что параметры записи не сравниваются должным образом на предмет равенства (они равны, только если параметры имеют один и тот же адрес - см. SameValue
в Delphi.Mocks.Helpers.pas
- Я знаю об этой проблеме, потому что это мой код, который используется с моего разрешения - некоторое время назад я написал лучшую версию, которая использовалась в Spring4D, в которой также есть фиктивный fwiw). Вот почему, даже если он не будет работать по кругу с вашим добавленнымGetCommandRecord
это может не пройти.
То, что я обычно предлагаю людям делать (пока я написал две имитирующие библиотеки для Delphi) при использовании макетов, должно быть максимально разрешительным. К счастью, Delphi Mocks поддерживает сопоставление параметров, которое позволяет указать, что на самом деле вам не так уж важно точное значение передаваемого параметра.
При этом просто измените настройку на вызов
MVMMock.Setup.Expect.Once.When.HandleCommands(It0.IsAny<TPsCommandRecord>);
Это сообщает внутреннему устройству сопоставления, записывающему вызовы макета из SUT, что не имеет значения, какое значение приходит, какое удовлетворяет ожиданиям.
Кстати по той же причине, что и с SameValue
ошибка не будет работать, используя It0.IsEqualTo(LCommandRecord)
потому что используемый компаратор для записей внутренне вызывает System.Generics.Defaults.Equals_Binary
который просто выполняет сравнение записи с плоской памятью, которая, возможно, не работает для любого ссылочного типа.