2010-05-20 2 views
2

Я в настоящее время в процессе начала работы с модульным тестированием и насмешливым навсегда, и я наткнулся на следующий метод, который я не могу показаться, чтобы изготовить рабочую макет реализации:Как мне высмеять метод с открытым параметром массива в PascalMock?

function GetInstance(const AIID: TGUID; 
         out AInstance; 
        const AArgs: array of const; 
        const AContextID: TImplContextID = CID_DEFAULT): Boolean; 

(TImplContextID это просто псевдоним типа для Integer)

Это как далеко я получил:

function TImplementationProviderMock.GetInstance(
    const AIID: TGUID; 
    out AInstance; 
    const AArgs: array of const; 
    const AContextID: TImplContextID): Boolean; 
var 
    lCall: TMockMethod; 
begin 
    lCall := AddCall('GetInstance').WithParams([@AIID, AContextID]); 
    Pointer(AInstance) := FindVarData(lCall.OutParams[0]).VPointer; 
    Result := lCall.ReturnValue; 
end; 

Но я не мог понять, как я предположительно, чтобы высмеять параметр открытого массива AArgs. Есть идеи?

Кроме того, там может быть более простой способ, чтобы вернуть out параметрическое AInstance и использует @ -notation для TGUID -typed параметра (по существу записи, т.е. тип значения) правильный путь?

Возможно ли издеваться над этим методом с текущей версией PascalMock?


Update 2: Я теперь вырубить текст вопроса для ясности. Первоначально он содержал следующее ошибочное выполнение фиктивного метода, который был, что ответ Мейсона относится к: «Неверный тип аргумента в переменной типа конструктора массива»

function TImplementationProviderMock.GetInstance(
    const AIID: TGUID; 
    out AInstance; 
    const AArgs: array of const; 
    const AContextID: TImplContextID): Boolean; 
begin 
    Result := AddCall('GetInstance') 
      .WithParams([@AIID, AContextID]) 
      .ReturnsOutParams([AInstance]) 
      .ReturnValue; 
end; 

В этом компилятор жаловался на .ReturnsOutParams([AInstance]) говоря.

+0

Вы можете получить его для компиляции, если вы добавите AArgs с @AArgs, но так как я не использую PascalMock Не уверен, что это приведет к желаемому поведению. –

ответ

0

Теперь я придумал несколько сложное решение, которое не совсем идеально подходит для POV OO- , потому что оно требует, чтобы разработчик теста знал, как макет реализован внутри, но я думаю, что это все еще несколько приемлемо так как не может быть сделано предположение о том, как иначе указать аргумент аргумента открытого массива в любом случае (по крайней мере, ни один из них не будет компилироваться).

Итак, это то, что реализация моего издевались метода теперь выглядит следующим образом:

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 -битовое действительно ожидаемый аргумент открытого массива.

0

Похоже, что ReturnsOutParams ожидает массив из const, который реализован внутри как массив TVarRec. TVarRec - это запись, которая вроде как вариант, но другая, и для ее компилятора требуется определенный тип. Неизученный параметр не войдет в него.

Возможно, такого рода вещи можно было бы сделать с расширенным RTTI Delphi 2010, но не с TVarRec.

+0

Я уже довольно уверен, что 'ReturnsOutParams' предполагается вызывать при определении ожиданий, а не в издевательском вызове. В действительности это не имеет никакого смысла. 'TMockMethod' также имеет свойство массива, называемое' OutParams', и я думаю, что он должен использоваться для возврата значений, ранее заполненных с помощью 'ReturnsOutParams'. –

+0

Это все еще оставляет вопрос о том, как издеваться над аргументом открытого массива ... –

+0

@Oliver: Опять же, я не думаю, что вы можете сделать это с помощью TVarRec. Я не эксперт PascalMock, но мне кажется, что эта функция слишком сложна для интерфейса, который он предоставляет. –

Смежные вопросы