Ad

How To Mock The Object Manager In Typo3 Unit-tests

- 1 answer

I'm writing some unit-tests for a typo3 v9.5 extension, and I can not figure how to properly mock objects when the under-test function is instanciating them using GeneralUtility::makeInstance(ObjectManager::class)->get(...)

If possible, I'd like to use the prophecy framework, but that's not mandatory.

For example, if the function under-test is like:

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

How could I test this and mock the Pageservice class?

I tried different variations of this solution:

$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());

But I get various cryptic errors every time. The given version raises the error:

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

Answer

Actually you should make use of dependency injection in the class which exposes the getRootline() API, then you can have the PageService injected this way:

final class MyCustomClass {
    private PageService $pageService;

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

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

While testing you can inject a mock instead:

$pageService = $this->prophesize(PageService::class);
$myCustomObject = new MyCustomClass($pageService->reveal());
Ad
source: stackoverflow.com
Ad