2010-05-20 45 views
2

我目前在入門單元測試和嘲諷良好的過程,我絆倒了以下的方法,我似乎無法制造一個工作模擬實現:如何在PascalMock中使用開放數組參數來模擬方法?

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

TImplContextID僅僅是整數類型別名)

這是多遠我得到:

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 -parameter AInstance一個更簡單的方式是使用@ -notation爲TGUID -typed參數(本質上是一個紀錄,即值類型),以正確的方式去?

是否有可能用當前版本的PascalMock嘲笑這種方法呢?


更新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不知道這是否會產生所需的行爲。 – 2010-05-20 16:42:09

回答

0

我現在想出了一個有點複雜的解決方案,它不完全適用於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; 

我有一個強烈的懷疑,這些程序很可能被大規模有人用的德爾福內部是怎樣處理動態和開放數組更深的理解進行了優化。

無論如何,在測試地點使用此解決方案時,我現在必須忽略模擬方法中甚至存在開放數組參數的事實。我簡單地指定期望這樣:

FMock.Expects('GetInstance').WithParams([@IMyIntf, 1, 2, 3, lContextID]).ReturnsOutParam(lDummy).Returns(True); 

...其中1, 2, 3位是真正的預計開放數組參數。

0

它看起來像ReturnsOutParams預計const陣列,它在內部實現爲一個TVarRec數組。 TVarRec是一種有點像變體但記錄不同的記錄,它需要編譯器定義的類型來填充它。一個無類型的參數不會進入它。

這種事情大概可以用Delphi 2010的擴展RTTI完成,但不能用TVarRec完成。

+0

我現在非常確定'ReturnsOutParams'應該在定義期望時被調用,而不是被模擬的調用。否則它並沒有真正的意義。 'TMockMethod'也有一個名爲'OutParams'的數組屬性,我認爲這應該用於返回之前通過'ReturnsOutParams'填充的值。 – 2010-05-20 15:50:24

+0

這仍然留下如何嘲笑開放數組參數的問題... – 2010-05-20 15:51:10

+0

@Oliver:我再次認爲你可以用TVarRec來做到這一點。我不是PascalMock專家,但在我看來,這個功能對於它提供的接口來說太複雜了。 – 2010-05-20 16:05:47

相關問題