Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Корректное создание TValue для работы с указателями Windows Threadpool API в Delphi-Mocks

Delphi , Компоненты и Классы , RTTI

В статье будет рассмотрен вопрос корректного создания объектов TValue для работы с указателями, возвращаемыми функциями Windows Threadpool API, при тестировании с использованием фреймворка Delphi-Mocks. В процессе решения проблемы будет использован язык Object Pascal, а также приведены примеры кода.

Оригинальный заголовок:

EInvalidCast wih mock function returning a pointer type

Введение

При работе с Windows Threadpool API многие функции возвращают указатели. При тестировании кода, обёртывающего данный API, возникает необходимость использования фреймворка Delphi-Mocks для создания моков. Однако, при попытке установить значения по умолчанию для мок-методов, возвращающих указатели, возникает исключение EInvalidCast. Это связано с тем, что интерфейс настройки моков TMock ожидает объект TValue для указания значения по умолчанию, которое должно быть корректно инициализировано.

Проблема

Разработчик столкнулся с проблемой при работе с моками функций, возвращающих указатели в интерфейсе IThreadPoolApi. При попытке установить значение по умолчанию для мок-метода CreateThreadPool с помощью метода WillReturnDefault возникло исключение EInvalidCast, так как TValue не был инициализирован корректно для хранения указателя типа PTP_POOL.

Решение

Для корректного создания TValue, содержащего указатель, необходимо использовать метод TValue.From<T>(). В данном случае, для указателя типа PTP_POOL, следует использовать:

apiMock.Setup.WillReturnDefault('CreateThreadPool', TValue.From<PTP_POOL>(PTP_POOL($FFFFFFFF)));

Также, при использовании метода WillExecute, необходимо возвращать TValue с использованием аналогичного подхода:

apiMock.Setup.WillExecute('CreateThreadpoolCleanupGroup',
    function (const args: TArray<TValue>; const ReturnType: TRttiType): TValue
    begin
        Result := TValue.From<PTP_CLEANUP_GROUP>(nil);
    end);

Важные замечания

При работе с TValue важно понимать различия в инициализации объектов для различных типов указателей. Например, при прямом присвоении нетипизированного nil-указателя TValue будет вызван метод TValue.Implicit(TObject), который вернёт свойство TValue.Empty. При использовании типизированного указателя, не являющегося указателем на TObject, будет вызван метод TValue.Implicit(TClass), который также вернёт TValue.Empty для nil-указателя, но вернёт TValue типа TClass с значением указателя в случае, если он не равен nil.

Заключение

Использование метода TValue.From<T>() позволяет корректно инициализировать TValue для хранения указателей, что является ключевым моментом при работе с моками в Delphi-Mocks. Приведённые примеры кода демонстрируют, как правильно настроить моки для функций, возвращающих указатели.

Пример кода

type
    PTP_POOL = Pointer;
    PTP_CLEANUP_GROUP = Pointer;

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

    TThreadPool = class(TInterfacedObject, IThreadPool)
    private
        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;
    FPTPPool := FTPApi.CreateThreadPool;
    // Проверка на не nullptr и т.д.
    FPTPCleanupGroup := FTPApi.CreateThreadpoolCleanupGroup;
    // Проверка на не nullptr и т.д.
end;

procedure ThreadPoolTest.TestFail_CreateThreadpoolCleanupGroup;
var
    apiMock: TMock<IThreadPoolApi>;
    testproc: TTestLocalMethod;
begin
    apiMock := TMock<IThreadPoolApi>.Create;
    apiMock.Setup.WillReturnDefault('CreateThreadPool', TValue.From<PTP_POOL>(PTP_POOL($FFFFFFFF)));
    apiMock.Setup.WillExecute('CreateThreadpoolCleanupGroup',
        function
            (const args: TArray<TValue>; const ReturnType: TRttiType): TValue
        begin
            Result := TValue.From<PTP_CLEANUP_GROUP>(nil);
        end);
    testproc := procedure
    var
        threadpool: IThreadPool;
    begin
        threadpool := TThreadPool.Create(apiMock);
    end;
    DUnitX.Assert.WillRaise(testproc, EThreadPoolError, 'Cannot create TP cleanup group');
end;

Итог

При правильном использовании метода TValue.From<T>() можно избежать исключения EInvalidCast и корректно настроить моки функций, возвращающих указатели, в Delphi-Mocks.

Создано по материалам из источника по ссылке.

Статья посвящена корректному созданию объектов `TValue` для работы с указателями в Windows Threadpool API и использованию фреймворка Delphi-Mocks для тестирования, с акцентом на решение проблемы с исключением `EInvalidCast`.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: RTTI ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-02-05 20:49:43/0.0031440258026123/0