如何在 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
类型参数(本质上是一条记录,即值类型)正确的做法是什么?
是否可以使用当前版本的 PascalMock 来模拟此方法?
更新 2:为了清楚起见,我现在删减了问题文本。最初,它包含以下模拟方法的错误实现,这就是 Mason 的回复所指的:
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])
说“变量类型数组构造函数中的参数类型错误” .”。
I'm currently in the process of getting started with unit testing and mocking for good and I stumbled over the following method that I can't seem to fabricate a working mock implementation for:
function GetInstance(const AIID: TGUID;
out AInstance;
const AArgs: array of const;
const AContextID: TImplContextID = CID_DEFAULT): Boolean;
(TImplContextID
is just a type alias for Integer)
This is how far I got:
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;
But I haven't been able to figure out how I am supposed to mock the open array parameter AArgs
. Any ideas?
Also, is there maybe a simpler way to to return the out
-parameter AInstance
and is using the @
-notation for the TGUID
-typed parameter (essentially a record, i.e. a value type) the right way to go?
Is it possible to mock this method with the current version of PascalMock at all?
Update 2: I have now cut down the question text for clarity. Originally it contained the following erroneous implementation of the mock method which was what Mason's reply refers to:
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;
In this the compiler complained about the .ReturnsOutParams([AInstance])
saying "Bad argument type in variable type array constructor.".
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
看起来
ReturnsOutParams
需要一个 const 数组,它在内部作为 TVarRec 数组实现。 TVarRec 是一个有点像变体但不同的记录,它需要编译器定义的类型来填充它。无类型参数不会进入其中。这种事情可能可以使用 Delphi 2010 的扩展 RTTI 来完成,但不能使用 TVarRec。
It looks like
ReturnsOutParams
expects an array of const, which is implemented internally as an array of TVarRec. TVarRec is a record that's sort of like a variant but different, and it requires a defined type for the compiler to fill it. An untyped parameter won't go into it.This sort of thing could probably be done with Delphi 2010's extended RTTI, but not with TVarRec.
我现在想出了一个有点复杂的解决方案,从面向对象的角度来看,它并不完全理想-
POV 因为它要求测试的实现者知道模拟是如何在内部实现的,但我认为这仍然是可以接受的,因为无论如何都不能做出关于如何指定开放数组参数期望的假设(至少没有一个可以编译) 。
所以,这就是我的模拟方法的实现现在的样子:
正如您所看到的,我的解决方案的核心是构造我自己的
TVarRec 数组
(又名TOpenArray
)然后我可以将其传递给WithParams
方法。我编写了几个实用程序例程,使我能够将显式参数与开放数组参数合并到一个新数组中。下面是 ConcatArrays 的实现:
我确实强烈怀疑这些例程可能会由对 Delphi 如何在内部处理动态和开放数组有更深入了解的人进行大规模优化。
无论如何,在测试站点上使用此解决方案后,我现在必须忽略模拟方法中甚至有一个开放数组参数的事实。我只是这样指定期望:
... 其中
1, 2, 3
位实际上是预期的开放数组参数。I've now come up with a somewhat elaborate solution which is not exactly ideal from an OO-
POV because it requires that the implementer of the test knows how the mock is implemented internally but I think that is still somewhat acceptable as no assumption can be made about how else to specify an open array argument expectation anyway (at least none that would compile).
So, this is what the implementation of my mocked method now looks like:
As you can see the heart of my solution was to construct my own
array of TVarRec
(akaTOpenArray
) which I could then pass to theWithParams
-method. I wrote a couple of utility routines that allowed me to merge the explicit arguments with the open array arguments into a single new array.Here is the implementation of
ConcatArrays
:I do have a strong suspicion that these routines could probably be massively optimized by someone with a deeper understanding of how Delphi handles dynamic and open arrays internally.
Anyway, with this solution in place at the test site I now have to ignore the fact that there even is an open array parameter in the mocked method. I simply specify the expectation as such:
... where the
1, 2, 3
-bit is really the expected open array argument.