Unit testing 调用了模拟函数,但预期($this->;once())失败
我正在测试一个Symfony命令来发送提醒短信。为此,我为我的文本消息接口创建了一个服务,并模拟了容器和文本消息服务: 正在测试的功能Unit testing 调用了模拟函数,但预期($this->;once())失败,unit-testing,symfony,mocking,phpunit,Unit Testing,Symfony,Mocking,Phpunit,我正在测试一个Symfony命令来发送提醒短信。为此,我为我的文本消息接口创建了一个服务,并模拟了容器和文本消息服务: 正在测试的功能 protected function textReminders() { $mailer = $this->getContainer()->get('mailer'); $em = $this->getContainer()->get( 'doctrine' )->getManager(); if ($t
protected function textReminders()
{
$mailer = $this->getContainer()->get('mailer');
$em = $this->getContainer()->get( 'doctrine' )->getManager();
if ($this->getContainer()->get('kernel')->getEnvironment() == 'dev'){
$debug = true;
}else{
$debug = false;
}
$textMessage = $this->getContainer()->get('text_messaging.interface');
$textMessage->sendSMS( $target, $content, $debug);
}
private function getMockContainer()
{
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\Container')
->disableOriginalConstructor()
->setMethods(array('get'))
->getMock();
return $container;
}
protected function setupMocks()
{
$mockText = $this->getMockBuilder('TextaHQ')
->disableOriginalConstructor()
->setMethods(array('sendSMS'))
->getMock();
$mockContainer = $this->getMockContainer();
$container = self::$kernel->getContainer();
$mockContainer->method('get')
->withConsecutive(['mailer'], ['doctrine'], ['kernel'], ['text_messaging.interface'])
->willReturnOnConsecutiveCalls(
$this->returnValue($container->get('mailer')),
$this->returnValue($container->get('doctrine')),
$this->returnValue(self::$kernel),
$this->returnValue($mockText))
;
$this->setMyMock([
'text' => $mockText,
'container' => $mockContainer
]);
}
public function testExecute()
{
$this->setupMocks();
self::bootKernel();
$application = new Application(self::$kernel);
$application->add(new ActionRemindCommand());
$command = $application->find( 'ahp:remind' );
$command->setContainer($this->getMyMock()['container']);
$commandTester = new CommandTester( $command );
$commandTester->execute( array(
'command' => $command->getName(),
'type' => 'text'
) );
$output = $commandTester->getDisplay();
$this->assertions();
}
protected function assertions()
{
$this->getMyMock()['text']
->expects( $this->once() )
->method( 'sendSMS' )
;
}
测试
protected function textReminders()
{
$mailer = $this->getContainer()->get('mailer');
$em = $this->getContainer()->get( 'doctrine' )->getManager();
if ($this->getContainer()->get('kernel')->getEnvironment() == 'dev'){
$debug = true;
}else{
$debug = false;
}
$textMessage = $this->getContainer()->get('text_messaging.interface');
$textMessage->sendSMS( $target, $content, $debug);
}
private function getMockContainer()
{
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\Container')
->disableOriginalConstructor()
->setMethods(array('get'))
->getMock();
return $container;
}
protected function setupMocks()
{
$mockText = $this->getMockBuilder('TextaHQ')
->disableOriginalConstructor()
->setMethods(array('sendSMS'))
->getMock();
$mockContainer = $this->getMockContainer();
$container = self::$kernel->getContainer();
$mockContainer->method('get')
->withConsecutive(['mailer'], ['doctrine'], ['kernel'], ['text_messaging.interface'])
->willReturnOnConsecutiveCalls(
$this->returnValue($container->get('mailer')),
$this->returnValue($container->get('doctrine')),
$this->returnValue(self::$kernel),
$this->returnValue($mockText))
;
$this->setMyMock([
'text' => $mockText,
'container' => $mockContainer
]);
}
public function testExecute()
{
$this->setupMocks();
self::bootKernel();
$application = new Application(self::$kernel);
$application->add(new ActionRemindCommand());
$command = $application->find( 'ahp:remind' );
$command->setContainer($this->getMyMock()['container']);
$commandTester = new CommandTester( $command );
$commandTester->execute( array(
'command' => $command->getName(),
'type' => 'text'
) );
$output = $commandTester->getDisplay();
$this->assertions();
}
protected function assertions()
{
$this->getMyMock()['text']
->expects( $this->once() )
->method( 'sendSMS' )
;
}
更新的测试,全部在一个文件中
public function testExecute()
{
$insertSql = 'echo "'
. str_replace(
array('"' ,'`' ),
array('\\"' ,'\\`'),
$this->getPrepSql() )
. '" | mysql ahp_example_com';
exec($insertSql);
self::bootKernel();
$mockText = $this->getMockBuilder('TextaHQ')
->disableOriginalConstructor()
->setMethods(array('sendSMS'))
->getMock();
$mockContainer = $this->getMockBuilder('Symfony\Component\DependencyInjection\Container')
->disableOriginalConstructor()
->setMethods(array('get'))
->getMock();
$container = self::$kernel->getContainer();
$mockContainer->method('get')
->withConsecutive(['mailer'], ['doctrine'], ['kernel'], ['text_messaging.interface'])
->willReturnOnConsecutiveCalls(
$this->returnValue($container->get('mailer')),
$this->returnValue($container->get('doctrine')),
$this->returnValue(self::$kernel),
$this->returnValue($mockText))
;
$application = new Application(self::$kernel);
$application->add(new ActionRemindCommand());
$mailer = self::$kernel->getContainer()->get('swiftmailer.mailer');
$logger = new \Swift_Plugins_MessageLogger();
$mailer->registerPlugin( $logger );
$this->setMailCollector($logger);
$output = '';
for($i=1;$i<=$this->getRunNoTimes();$i++) {
$command = $application->find( 'ahp:remind' );
$command->setContainer($mockContainer);
$commandTester = new CommandTester( $command );
$commandTester->execute( array(
'command' => $command->getName(),
'type' => 'text'
) );
$output .= $commandTester->getDisplay();
}
$mockText
->expects( $this->once() )
->method( 'sendSMS' )
;
}
public function testExecute()
{
$insertSql='echo''
.str_替换(
数组(“,”`'),
数组(“\\”,“\\`'),
$this->getPrepSql())
“| mysql ahp_example_com”;
exec($insertSql);
self::引导内核();
$mockText=$this->getMockBuilder('TextaHQ')
->disableOriginalConstructor()
->setMethods(数组('sendSMS'))
->getMock();
$mockContainer=$this->getMockBuilder('Symfony\Component\DependencyInjection\Container'))
->disableOriginalConstructor()
->setMethods(数组('get'))
->getMock();
$container=self::$kernel->getContainer();
$mockContainer->method('get')
->连续(['mailer']、['doctrine']、['kernel']、['text_messaging.interface']))
->将返回执行调用(
$this->returnValue($container->get('mailer')),
$this->returnValue($container->get('doctrine')),
$this->returnValue(self::$kernel),
$this->returnValue($mockText))
;
$application=新应用程序(self:$kernel);
$application->add(新的actionememendmentcommand());
$mailer=self::$kernel->getContainer()->get('swiftmailer.mailer');
$logger=new\Swift\u Plugins\u MessageLogger();
$mailer->registerPlugin($logger);
$this->setMailCollector($logger);
$output='';
对于($i=1;$igetRunNoTimes();$i++){
$command=$application->find('ahp:remind');
$command->setContainer($mockContainer);
$commandTester=新commandTester($command);
$commandTester->执行(数组)(
'command'=>$command->getName(),
'键入'=>'文本'
) );
$output.=$commandTester->getDisplay();
}
$mockText
->预期($this->once())
->方法('sendSMS')
;
}
**PHPStorm测试调用**
/usr/bin/php /home/jochen/projects/ahp/trunk/vendor/phpunit/phpunit/phpunit --configuration /home/jochen/projects/ahp/trunk/app/phpunit.xml.dist AgriHealth\AhpBundle\Tests\Command\ActionRemindCommandVet7DaysBeforeTest /home/jochen/projects/ahp/trunk/src/AgriHealth/AhpBundle/Tests/Command/RemindText/ActionRemindCommandVet7DaysBeforeTest.php --teamcity
Testing started at 10:25 AM ...
PHPUnit 5.5.4 by Sebastian Bergmann and contributors.
Expectation failed for method name is equal to <string:sendSMS> when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.
Time: 1.12 seconds, Memory: 18.00MB
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
Process finished with exit code 1
/usr/bin/php/home/jochen/projects/ahp/trunk/vendor/phpunit/phpunit/phpunit--configuration/home/jochen/projects/ahp/trunk/app/phpunit.xml.dist agrichealth\AhpBundle\Tests\Command\actionmembrandvet7天前重新测试/home/jochen/projects/ahp/trunk/src/AgriHealth/AhpBundle/Tests/Command/rementtext/actionrementcommandvet7daysbeforetest.php——teamcity
测试于上午10:25开始。。。
PHPUnit 5.5.4由塞巴斯蒂安·伯格曼和贡献者撰写。
调用1次时,方法名称等于的预期失败。
方法应被调用1次,实际调用0次。
时间:1.12秒,内存:18.00MB
失败!
测试:1,断言:1,失败:1。
进程已完成,退出代码为1
调试测试时,我可以看到$textMessage是一个模拟
但是,在assertions()中的测试结束时,我得到一个错误:
Expectation failed for method name is equal to <string:sendsms> when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.
调用1次时,方法名称等于的预期失败。
方法应被调用1次,实际调用0次。
调试器将模拟的函数显示为小写:“sendsms”,但重命名该函数没有帮助。下面是一个小的虚幻案例,以澄清我在评论中提到的要点。此外,对于在方法的实际调用执行后设置期望值的情况,它还有一个失败的测试(这看起来是一个多功能方法更新测试的情况)
class MyClass
{
public function someMethod(){
}
}
class ExpectationsTest extends PHPUnit_Framework_TestCase
{
private $myClassMock;
public function setUp(){
$this->myClassMock = $this->getMock('MyClass');
}
public function testLocalMock(){
$localMock = $this->getMock('MyClass');
$localMock->expects($this->once())
->method('someMethod');
$localMock->someMethod();
}
public function testClassScopeMockInstance(){
$this->myClassMock->expects($this->once())
->method('someMethod');
$this->myClassMock->someMethod();
}
public function testWillFailBecauseExpectationWasSetAfterCall(){
$this->myClassMock->someMethod();
$this->myClassMock->expects($this->once())
->method('someMethod');
}
public function testCanUseHelperToCreateLocalMock(){
$mock = $this->createMyClassMock();
$mock->expects($this->once())
->method('someMethod');
$mock->someMethod();
}
private function createMyClassMock(){
return $this->getMock('MyClass');
}
public function testCanSetExpectationsInHelper(){
$this->setExpecatationsOnTestCaseScopeMock();
$this->myClassMock->someMethod();
}
private function setExpecatationsOnTestCaseScopeMock(){
$this->myClassMock->expects($this->once())
->method('someMethod');
}
}
顺便说一句,我想我第一次对你的代码研究得不够透彻。我想我可能误解了你的
setupmock
和getMyMock
是如何工作的。对此我深表歉意。看起来你的模拟配置超出了testExecute
的范围。这意味着你不能通过$t隐藏你的模拟his->setMyMock()
并在以后使用$this->getMyMock()将其解压缩
用于断言。PHPUnit将无法跟踪调用。更多详细信息:我这样做是为了集中创建模拟对象和一组测试的测试执行。每个测试只有输入数据和结果更改。这是不可能的。我必须反复重复吗?更准确地说,你可以创建inst在testMethod
之外对模拟对象进行一些常规配置,但所有的表达式都必须在testMethod
内部定义。这是因为PHPUnit将这些期望绑定到此testMethod
(当调用testMethod
时,所有的期望值都被注册为该方法的期望值)。谢谢@xmike,我现在已经将所有内容都放在一个脚本中,它仍然不起作用。还有其他想法吗?如果我理解正确,我的测试范围是一个类