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