Home > database >  Symfony PHPUnit Mock single Method without disabling constructor
Symfony PHPUnit Mock single Method without disabling constructor

Time:10-20

I've got a class that's using ContainerBagInterface:

class NotificationService
{
    private ContainerBagInterface $params;

    public function __construct(ContainerBagInterface $params)
    {
        $this->params = $params;
    }

    public function send(string $message, string $channelId): void
    {
        // ...
    }

    public function log(string $message): void
    {
        $this->send(
            $message,
            $this->params->get('app.log_channel_id')
        );
    }
}

And I'd like to test if calling log triggers a call of send.

I tried to partially mock the Service like this:

final class NotificationServiceTest extends KernelTestCase
{
    public function testLog(): void
    {
        $notificationServiceMock = $this->createPartialMock(
            NotificationService::class,
            ['send']
        );

        $notificationServiceMock->expects(self::once())
            ->method('send')
            ->with('test', 'log-channel-id');

        $notificationServiceMock->log('test');
    }
}

Which results in the following error:

Error: Typed property App\Service\NotificationService::$params must not be accessed before initialization

When enabling my constructor to circumvent this error like that:

$notificationServiceMock = $this->getMockBuilder(NotificationService::class)
    ->enableOriginalConstructor()
    ->onlyMethods(['send'])
    ->getMock();

I receive this error:

ArgumentCountError: Too few arguments to function App\Service\NotificationService::__construct(), 0 passed in ... and exactly 1 expected

Feels like I'm going around in circles.

CodePudding user response:

The method setConstructorArgs will be your friend :)

First, mock your ContainerBag into $mockerContainerBag variable

$notificationServiceMock = $this->getMockBuilder(NotificationService::class)
    ->enableOriginalConstructor()
    ->setConstructorArgs([$mockerContainerBag])
    ->onlyMethods(['send'])
    ->getMock();
  • Related