Я сейчас придумал несколько сложное решение, которое не совсем идеально с точки зрения OO-
POV, потому что это требует, чтобы разработчик теста знал, как макет реализован внутри, но я думаю, что это все еще несколько приемлемо, так как нельзя делать никаких предположений о том, как еще указать ожидание аргумента в открытом массиве (по крайней мере, ни одно из них не скомпилирует) .
Итак, вот как выглядит реализация моего смоделированного метода:
function TImplementationProviderMock.GetInstance(
const AIID: TGUID;
out AInstance;
const AArgs: array of const;
const AContextID: TImplContextID): Boolean;
var
lCall: TMockMethod;
lArgs: TOpenArray;
begin
lArgs := ConcatArrays([ArgsToArray([@AIID]), ArgsToArray(AArgs), ArgsToArray([AContextID])]);
lCall := AddCall('GetInstance').WithParams(lArgs);
Pointer(AInstance) := FindVarData(lCall.OutParams[0]).VPointer;
Result := lCall.ReturnValue;
end;
Как вы видите, суть моего решения состояла в том, чтобы создать мой собственный array of TVarRec
(он же TOpenArray
), который я мог бы затем передать методу WithParams
. Я написал несколько служебных программ, которые позволили мне объединить явные аргументы с аргументами открытого массива в один новый массив.
Вот реализация ConcatArrays
:
type TOpenArray = array of TVarRec;
function ConcatArrays(const AArrays: array of TOpenArray): TOpenArray;
var
lLength: Integer;
lArray: TOpenArray;
lIdx: Integer;
lElem: TVarRec;
begin
lLength := 0;
for lArray in AArrays do
Inc(lLength, Length(lArray));
SetLength(Result, lLength);
lIdx := -1;
for lArray in AArrays do
for lElem in lArray do
begin
Inc(lIdx);
Result[lIdx] := lElem;
end;
end;
У меня есть сильное подозрение, что эти подпрограммы, вероятно, могут быть массово оптимизированы кем-то, кто лучше понимает, как Delphi обрабатывает динамические и открытые массивы внутри.
В любом случае, с этим решением на месте тестирования, я теперь должен игнорировать тот факт, что в методе mocked есть даже параметр открытого массива. Я просто указываю ожидание как таковое:
FMock.Expects('GetInstance').WithParams([@IMyIntf, 1, 2, 3, lContextID]).ReturnsOutParam(lDummy).Returns(True);
... где 1, 2, 3
-бит действительно является ожидаемым аргументом открытого массива.