gpt4 book ai didi

delphi - EInvalidCast 与模拟函数返回指针类型

转载 作者:行者123 更新时间:2023-12-01 19:37:12 24 4
gpt4 key购买 nike

我编写了一个接口(interface)来包装 Windows Threadpool API,其中许多函数返回普通的 Pointer 类型。

现在我正在编写测试并想使用 delphi-mocks framework模拟该包装器接口(interface)。

问题是 TMock 设置接口(interface)需要一个 TValue 对象来指定模拟函数的默认返回值,我看不到如何做的方法正确地从可用的 TValue功能。尽管我已经看到 ekPointer 是有效的 TTypeKind值。

当调用模拟函数时,我从相应的 RTTI 调用中收到 EInvalidCast 异常。
当 RTTI 调用尝试从隐式 TValue 对象转换返回类型值时,就会发生这种情况。

我的代码大致如下1:

type
PTP_POOL = Pointer;
PTP_CLEANUP_GROUP = Pointer;

IThreadPoolApi = interface(IInterface)
{...}
function CreateThreadPool() : PTP_POOL;
function CreateThreadpoolCleanupGroup() : PTP_CLEANUP_GROUP;
{...}
end;

被测类

type
TThreadPool = class(TInterfacedObject, IThreadPool)
FTPApi : IThreadPoolApi;
FPTPPool : PTP_POOL;
FPTPCleanupGroup : PTP_CLEANUP_GROUP;
{...}
public
constructor Create(iapi : IThreadPoolApi);
end;

implementation
constructor TThreadPool.Create(iapi : IThreadPoolApi);
begin
inherited Create();
FTPApi := iapi;

{**** Here I get a EInvalidCast exception when mocking the interface ****}
FPTPPool := FTPApi.CreateThreadPool();
if(not assigned(FPTPPool)) then
begin
{Raise exception}
raise EThreadPoolError('Cannot create TP thread pool');
end;

{**** This case should be tested ****}
FPTPCleanupGroup := FTPApi.CreateThreadpoolCleanupGroup();
if(not assigned(FPTPPool)) then
begin
{Raise exception}
raise EThreadPoolError('Cannot create TP cleanup group');
end;

{...}
end;

以及测试内容

procedure ThreadPoolTest.TestFail_CreateThreadpoolCleanupGroup();
var
apiMock : TMock<IThreadPoolApi>;
testproc : TTestLocalMethod;
begin
apiMock := TMock<IThreadPoolApi>Create();
{**** Needed to reach the call of CreateThreadpoolCleanupGroup
but EInvalidCast is raised ****}
apiMock.Setup.WillReturnDefault('CreateThreadPool',PTP_POOL($FFFFFFFF));
{**** The case to be tested ****}
apiMock.Setup.WillExecute('CreateThreadpoolCleanupGroup',
function (const args : TArray<TValue>; const ReturnType : TRttiType)
: TValue
begin
result := nil;
end);

testproc :=
procedure()
var
threadpool : IThreadPool;
begin
threadpool := TThreadPool.Create(apiMock);
end;
DUnitX.Assert.WillRaise(testproc,EThreadPoolError,
'Cannot create TP cleanup group');
end;

TL;DR;

所以问题是:
我需要做什么才能正确创建 TValue 以包含 PTP_POOL 指针类型?


1)设置MCVE的代码有点太多了。 ,所以我只是在这里简单介绍一下背景,请参阅 {**** 突出显示的注释 ****}

最佳答案

将原始指针分配给 TValue 时,使用 TValue.From<T>() 方法,例如:

TValue.From<PTP_POOL>(nil);

或者,如果您想返回文字值:

TValue.From<PTP_POOL>(PTP_POOL(value));

TValue没有原始指针的隐式转换,但它确实有 TObject 的隐式转换。和TClass指针。

如果将无类型 nil 指针直接分配给 TValue ,它调用 TValue.Implicit(TObject) ,这将返回 TValue.Empty传递 nil 指针时的属性。

如果您分配一个类型化的非 TObject直接指向 TValue ,它调用 TValue.Implicit(TClass) ,返回 TValue.Empty如果指针为零,否则返回 TValue类型 TClass与指针的值,即使它实际上没有指向有效的类类型。

如果您将指针传递给 TValue.From<T>() ,它返回 TValue类型 T与指针的值,即使它是零。

这种差异很微妙,但非常重要。

关于delphi - EInvalidCast 与模拟函数返回指针类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46433385/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com