PhpUnit 检查多个日志消息
PhpUnit check for more than one log message
在我的项目中,我有一个 class 实现外观模式,这意味着我有一个方法,它在后台调用大量 classes 并做“事情”。其中之一是在发送电子邮件后写几条日志消息。
因此,当写入日志消息时,我知道电子邮件已发送。此外,被调用的 classes 会写入一些日志消息。
所以我的任务是检查一堆触发的日志消息,如果至少有一个符合我的预期。
我知道如何模拟我的记录器,所以我可以检查一条日志消息是否存在。但我需要的是检查是否写入了多个日志消息。我成功了我知道我的门面方法调用触发了所有正确的 classes/methods.
这是我现在拥有的,但显然不起作用:
...
$mockLogger = $this->createMock(LoggerInterface::class);
$mockLogger->expects($this->any())
->method('info')
->with($this->stringContains('Owner mail sent to'));
$mockLogger->expects($this->any())
->method('info')
->with($this->stringContains('Pno mail sent to'));
$mockLogger->expects($this->any())
->method('info')
->with($this->stringContains('Group mail sent to'));
$this->facade->setLogger($mockLogger);
$this->facade->sendEMails($reportDto);
这是我得到的错误:
Testing App\Tests\Unit\Domain\Mail\MailingFacadeTest
Mailing Facade (App\Tests\Unit\Domain\Mail\MailingFacade)
✘ Send e mails
┐
├ Expectation failed for method name is "info" when invoked 1 time(s)
├ Parameter 0 for invocation Psr\Log\LoggerInterface::info('Group mail sent to gf.test@ex...port 1', Array ()) does not match expected value.
├ Failed asserting that 'Group mail sent to gf.test@example.com as p221903 for Report 1' contains "pno mail sent to ".
│
╵ /var/www/src/Logger/LoggerTrait.php:72
╵ /var/www/src/Domain/Mail/MailingFacade.php:59
╵ /var/www/src/Domain/Mail/MailingFacade.php:34
╵ /var/www/tests/Unit/Domain/Mail/MailingFacadeTest.php:63
┴
有没有办法检查具有特定字符串的日志消息是否至少被写入日志一次?
您要查找的函数是 withConsecutive()
而不是 with()
。这允许您传递多个参数。您的断言将如下所示:
$mockLogger->expects($this->exactly(3))
->method('info')
->withConsecutive(['Owner mail sent to'],['Pno mail sent to'],['Group mail sent to']);
传递的参数在数组中,因为当然可以在一次调用中调用具有多个参数的函数。然后您可以传入一个包含多个变量的数组来测试它。
与其尝试从模拟中设置 'expections',我发现注入记录器(实现 Psr\Log\LoggerInterface
)以收集发送到日志的所有消息要容易得多,并且然后在通话后检查。 Monolog 有一个 'TestHandler' 例如,它可能是这样的:
<?php
$log = new \Monolog\Logger('test');
$testLog = new \Monolog\Handler\TestHandler();
$log->pushHandler($testLog);
$this->facade = new className($log);
$this->facade->sendEMails(new DtoObject('x', 'y'));
$this->assertTrue(
$testLog->hasInfoThatContains('Owner mail sent to')
|| $testLog->hasInfoThatContains('Pno mail sent to')
|| $testLog->hasInfoThatContains('Group mail sent to'),
'None of the possible messages were found'
);
我有一个可以在 PHPUnit 测试中使用的 Trait,它创建了 $this->log
和 $this->testLog
,因此可以使用和读取它们。
在我的项目中,我有一个 class 实现外观模式,这意味着我有一个方法,它在后台调用大量 classes 并做“事情”。其中之一是在发送电子邮件后写几条日志消息。 因此,当写入日志消息时,我知道电子邮件已发送。此外,被调用的 classes 会写入一些日志消息。
所以我的任务是检查一堆触发的日志消息,如果至少有一个符合我的预期。
我知道如何模拟我的记录器,所以我可以检查一条日志消息是否存在。但我需要的是检查是否写入了多个日志消息。我成功了我知道我的门面方法调用触发了所有正确的 classes/methods.
这是我现在拥有的,但显然不起作用:
...
$mockLogger = $this->createMock(LoggerInterface::class);
$mockLogger->expects($this->any())
->method('info')
->with($this->stringContains('Owner mail sent to'));
$mockLogger->expects($this->any())
->method('info')
->with($this->stringContains('Pno mail sent to'));
$mockLogger->expects($this->any())
->method('info')
->with($this->stringContains('Group mail sent to'));
$this->facade->setLogger($mockLogger);
$this->facade->sendEMails($reportDto);
这是我得到的错误:
Testing App\Tests\Unit\Domain\Mail\MailingFacadeTest
Mailing Facade (App\Tests\Unit\Domain\Mail\MailingFacade)
✘ Send e mails
┐
├ Expectation failed for method name is "info" when invoked 1 time(s)
├ Parameter 0 for invocation Psr\Log\LoggerInterface::info('Group mail sent to gf.test@ex...port 1', Array ()) does not match expected value.
├ Failed asserting that 'Group mail sent to gf.test@example.com as p221903 for Report 1' contains "pno mail sent to ".
│
╵ /var/www/src/Logger/LoggerTrait.php:72
╵ /var/www/src/Domain/Mail/MailingFacade.php:59
╵ /var/www/src/Domain/Mail/MailingFacade.php:34
╵ /var/www/tests/Unit/Domain/Mail/MailingFacadeTest.php:63
┴
有没有办法检查具有特定字符串的日志消息是否至少被写入日志一次?
您要查找的函数是 withConsecutive()
而不是 with()
。这允许您传递多个参数。您的断言将如下所示:
$mockLogger->expects($this->exactly(3))
->method('info')
->withConsecutive(['Owner mail sent to'],['Pno mail sent to'],['Group mail sent to']);
传递的参数在数组中,因为当然可以在一次调用中调用具有多个参数的函数。然后您可以传入一个包含多个变量的数组来测试它。
与其尝试从模拟中设置 'expections',我发现注入记录器(实现 Psr\Log\LoggerInterface
)以收集发送到日志的所有消息要容易得多,并且然后在通话后检查。 Monolog 有一个 'TestHandler' 例如,它可能是这样的:
<?php
$log = new \Monolog\Logger('test');
$testLog = new \Monolog\Handler\TestHandler();
$log->pushHandler($testLog);
$this->facade = new className($log);
$this->facade->sendEMails(new DtoObject('x', 'y'));
$this->assertTrue(
$testLog->hasInfoThatContains('Owner mail sent to')
|| $testLog->hasInfoThatContains('Pno mail sent to')
|| $testLog->hasInfoThatContains('Group mail sent to'),
'None of the possible messages were found'
);
我有一个可以在 PHPUnit 测试中使用的 Trait,它创建了 $this->log
和 $this->testLog
,因此可以使用和读取它们。