如何在 Typo3 单元测试中模拟对象管理器

How to mock the object manager in Typo3 unit-tests

我正在为 typo3 v9.5 扩展编写一些单元测试,但当被测函数使用 GeneralUtility::makeInstance(ObjectManager::class)->get(...)[=15= 实例化对象时,我不知道如何正确模拟对象]

如果可能,我想使用 the prophecy framework,但这不是强制性的。

例如,如果被测函数是这样的:

public function getRootline($pageUid) {
    $pageService = GeneralUtility::makeInstance(ObjectManager::class)->get(PageService::class);
    return $pageService->getRootLine($pageUid);
}

我如何测试它并模拟 Pageservice class?

我尝试了此解决方案的不同变体:

$pageServiceProphecy = $this->prophesize(PageService::class);
$pageServiceProphecy->getRootLine($pageUid)->shouldBeCalled()->willReturn($myRootLine);

$omProphecy = $this->prophesize(ObjectManager::class);
$omProphecy->get(PageService::class)->shouldBeCalled()->willReturn($pageServiceProphecy);

GeneralUtility::setSingletonInstance(ObjectManager::class, $omProphecy->reveal());

但我每次都会收到各种神秘错误。 给定版本引发错误:

TYPO3\CMS\Core\Cache\Exception\NoSuchCacheException: A cache with identifier "cache_runtime" does not exist.

实际上你应该在暴露getRootline() API的class中使用dependency injection,然后你可以用这种方式注入PageService :

final class MyCustomClass {
    private PageService $pageService;

    public function __construct(PageService $pageService)
    {
        $this->pageService = $pageService;
    }

    public function getRootline(int $pageUid)
    {
        return $this->pageService->getRootLine($pageUid);
    }
}

在测试时,您可以改为注入模拟:

$pageService = $this->prophesize(PageService::class);
$myCustomObject = new MyCustomClass($pageService->reveal());