PHPunit模拟对象,并根据对象属性值对连续调用进行不同的响应
我模拟一个类的函数,并试图根据给定对象(模拟函数的参数)的属性返回不同的值 在我的代码下面,有一些评论:PHPunit模拟对象,并根据对象属性值对连续调用进行不同的响应,php,phpunit,Php,Phpunit,我模拟一个类的函数,并试图根据给定对象(模拟函数的参数)的属性返回不同的值 在我的代码下面,有一些评论: 我嘲笑FacebookHelper类 我对getExternalCampaignData(Campaign$Campaign)函数感兴趣,所以我正在“操纵”它以 我想根据活动id更改返回值 PHP:7.0.18和PHPunit版本:5.7.20 代码 use AppBundle\Entity\Campaign; use Monolog\Logger; use PHPUnit\Framew
- 我嘲笑FacebookHelper类
- 我对getExternalCampaignData(Campaign$Campaign)函数感兴趣,所以我正在“操纵”它以
- 我想根据活动id更改返回值
- PHP:7.0.18和PHPunit版本:5.7.20
use AppBundle\Entity\Campaign;
use Monolog\Logger;
use PHPUnit\Framework\TestCase;
class FacebookHelperTest extends TestCase {
public function testIfStatusSyncIsSetCorrectly() {
$campaign = new Campaign();
/** @var \PHPUnit_Framework_MockObject_MockObject|Logger $logger */
$logger = $this->createMock(Logger::class);
/** @var \PHPUnit_Framework_MockObject_MockObject|FacebookHelper $helper */
$builder = $this->getMockBuilder(FacebookHelper::class)->disableOriginalConstructor()->setMethods(['getExternalCampaignData']);
$helper = $builder->getMock();
$helper->expects($this->exactly(3))
->method('getExternalCampaignData')
->withConsecutive(
[$this->callback(function(Campaign $campaign) { var_dump($campaign->getFbCampaignId(), "expecting 1"); return $campaign->getFbCampaignId() == 1; })],
[$this->callback(function(Campaign $campaign) { var_dump($campaign->getFbCampaignId(), "expecting 2"); return $campaign->getFbCampaignId() == 2; })],
[$this->callback(function(Campaign $campaign) { var_dump($campaign->getFbCampaignId(), "expecting 3"); return $campaign->getFbCampaignId() == 3; })]
)
->willReturnOnConsecutiveCalls(
['campaign' => ['status' => FacebookHelper::CAMPAIGN_STATUS_ACTIVE]],
['campaign' => ['status' => FacebookHelper::CAMPAIGN_STATUS_ACTIVE]],
['campaign' => ['status' => FacebookHelper::CAMPAIGN_STATUS_ARCHIVED]]
);
$campaign->setFbCampaignId(1);
$campaign->setStatus('active');
$modifiedCampaign = $helper->modifyCampaignIfNeeded($campaign, $logger);
$this->assertFalse($modifiedCampaign->getSettings('fb_status_out_of_sync'));
$campaign->setFbCampaignId(2);
$campaign->setStatus('paused');
$modifiedCampaign = $helper->modifyCampaignIfNeeded($campaign, $logger);
$this->assertTrue($modifiedCampaign->getSettings('fb_status_out_of_sync'));
$campaign->setFbCampaignId(3);
$campaign->setStatus('paused');
$modifiedCampaign = $helper->modifyCampaignIfNeeded($campaign, $logger);
$this->assertTrue($modifiedCampaign->getSettings('fb_status_out_of_sync'));
}
}
当我运行上面的单元测试时,一切似乎都正常工作。
除了行为有点奇怪之外,回调调用的次数太多了
我已经发现了一个可能导致以下情况的错误:
因此,我将phpunit更新为5.7.20版,希望这个问题在那里得到解决
或者我需要用不同的方法
PHPunit的结果
use AppBundle\Entity\Campaign;
use Monolog\Logger;
use PHPUnit\Framework\TestCase;
class FacebookHelperTest extends TestCase {
public function testIfStatusSyncIsSetCorrectly() {
$campaign = new Campaign();
/** @var \PHPUnit_Framework_MockObject_MockObject|Logger $logger */
$logger = $this->createMock(Logger::class);
/** @var \PHPUnit_Framework_MockObject_MockObject|FacebookHelper $helper */
$builder = $this->getMockBuilder(FacebookHelper::class)->disableOriginalConstructor()->setMethods(['getExternalCampaignData']);
$helper = $builder->getMock();
$helper->expects($this->exactly(3))
->method('getExternalCampaignData')
->withConsecutive(
[$this->callback(function(Campaign $campaign) { var_dump($campaign->getFbCampaignId(), "expecting 1"); return $campaign->getFbCampaignId() == 1; })],
[$this->callback(function(Campaign $campaign) { var_dump($campaign->getFbCampaignId(), "expecting 2"); return $campaign->getFbCampaignId() == 2; })],
[$this->callback(function(Campaign $campaign) { var_dump($campaign->getFbCampaignId(), "expecting 3"); return $campaign->getFbCampaignId() == 3; })]
)
->willReturnOnConsecutiveCalls(
['campaign' => ['status' => FacebookHelper::CAMPAIGN_STATUS_ACTIVE]],
['campaign' => ['status' => FacebookHelper::CAMPAIGN_STATUS_ACTIVE]],
['campaign' => ['status' => FacebookHelper::CAMPAIGN_STATUS_ARCHIVED]]
);
$campaign->setFbCampaignId(1);
$campaign->setStatus('active');
$modifiedCampaign = $helper->modifyCampaignIfNeeded($campaign, $logger);
$this->assertFalse($modifiedCampaign->getSettings('fb_status_out_of_sync'));
$campaign->setFbCampaignId(2);
$campaign->setStatus('paused');
$modifiedCampaign = $helper->modifyCampaignIfNeeded($campaign, $logger);
$this->assertTrue($modifiedCampaign->getSettings('fb_status_out_of_sync'));
$campaign->setFbCampaignId(3);
$campaign->setStatus('paused');
$modifiedCampaign = $helper->modifyCampaignIfNeeded($campaign, $logger);
$this->assertTrue($modifiedCampaign->getSettings('fb_status_out_of_sync'));
}
}
Testing started at 10:40 AM ...
Nothing to update - your database is already in sync with the current entity metadata.
PHPUnit 5.7.20 by Sebastian Bergmann and contributors.
Expectation failed for method name is equal to <string:getExternalCampaignData> when invoked 3 time(s)
Parameter 0 for invocation #0 AppBundle\Services\FacebookHelper::getExternalCampaignData(AppBundle\Entity\Campaign Object (...)) does not match expected value.
Failed asserting that AppBundle\Entity\Campaign Object &0000000026aee99e00000000359c8973 (
...
'status' => 'paused'
...
'fb_campaign_id' => 2
...
'settings' => Array &1 (
'fb_status_out_of_sync' => false
)
...
) is accepted by specified callback.
/home/ali/www/src/AppBundle/Services/FacebookHelper.php:1227
/home/ali/www/tests/AppBundle/Services/FacebookHelperTest.php:41
int(1)
string(11) "expecting 1"
int(1)
string(11) "expecting 1"
int(2)
string(11) "expecting 2"
int(2)
string(11) "expecting 1"
Time: 702 ms, Memory: 6.00MB
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
Process finished with exit code 1
测试于上午10:40开始。。。
无需更新-您的数据库已与当前实体元数据同步。
PHPUnit 5.7.20由塞巴斯蒂安·伯格曼和贡献者撰写。
调用3次时,方法名称等于的预期失败
调用#0 AppBundle\Services\FacebookHelper::getExternalCampaignData(AppBundle\Entity\Campaign Object(…)的参数0与预期值不匹配。
断言AppBundle\Entity\Campaign对象&00000000 26AEE99E00000000359C8973失败(
...
“状态”=>“已暂停”
...
“fb_活动id”=>2
...
“设置”=>数组和1(
“fb\U状态\u不同步”=>错误
)
...
)由指定的回调函数接受。
/home/ali/www/src/AppBundle/Services/FacebookHelper.php:1227
/home/ali/www/tests/AppBundle/Services/FacebookHelperTest.php:41
int(1)
字符串(11)“应为1”
int(1)
字符串(11)“应为1”
int(2)
字符串(11)“应为2”
int(2)
字符串(11)“应为1”
时间:702ms,内存:6.00MB
失败!
测试:1,断言:1,失败:1。
进程已完成,退出代码为1
Oke,所以在大量搜索之后,我检查了phpunit测试本身的单元测试(paradox:p?),最后发现了它是如何工作的
解决方案
use AppBundle\Entity\Campaign;
use Monolog\Logger;
use PHPUnit\Framework\TestCase;
class FacebookHelperTest extends TestCase {
public function testIfStatusSyncIsSetCorrectly() {
$campaign = new Campaign();
/** @var \PHPUnit_Framework_MockObject_MockObject|Logger $logger */
$logger = $this->createMock(Logger::class);
/** @var \PHPUnit_Framework_MockObject_MockObject|FacebookHelper $helper */
$builder = $this->getMockBuilder(FacebookHelper::class)->disableOriginalConstructor()->setMethods(['getExternalCampaignData']);
$helper = $builder->getMock();
$helper->expects($this->exactly(3))
->method('getExternalCampaignData')
->withConsecutive(
[$this->callback(function(Campaign $campaign) { var_dump($campaign->getFbCampaignId(), "expecting 1"); return $campaign->getFbCampaignId() == 1; })],
[$this->callback(function(Campaign $campaign) { var_dump($campaign->getFbCampaignId(), "expecting 2"); return $campaign->getFbCampaignId() == 2; })],
[$this->callback(function(Campaign $campaign) { var_dump($campaign->getFbCampaignId(), "expecting 3"); return $campaign->getFbCampaignId() == 3; })]
)
->willReturnOnConsecutiveCalls(
['campaign' => ['status' => FacebookHelper::CAMPAIGN_STATUS_ACTIVE]],
['campaign' => ['status' => FacebookHelper::CAMPAIGN_STATUS_ACTIVE]],
['campaign' => ['status' => FacebookHelper::CAMPAIGN_STATUS_ARCHIVED]]
);
$campaign->setFbCampaignId(1);
$campaign->setStatus('active');
$modifiedCampaign = $helper->modifyCampaignIfNeeded($campaign, $logger);
$this->assertFalse($modifiedCampaign->getSettings('fb_status_out_of_sync'));
$campaign->setFbCampaignId(2);
$campaign->setStatus('paused');
$modifiedCampaign = $helper->modifyCampaignIfNeeded($campaign, $logger);
$this->assertTrue($modifiedCampaign->getSettings('fb_status_out_of_sync'));
$campaign->setFbCampaignId(3);
$campaign->setStatus('paused');
$modifiedCampaign = $helper->modifyCampaignIfNeeded($campaign, $logger);
$this->assertTrue($modifiedCampaign->getSettings('fb_status_out_of_sync'));
}
}
$helper->expects($this->exactly(3))
->method('getExternalCampaignData')
->will(
$this->returnCallback(
function(Campaign $campaign) {
if($campaign->getFbCampaignId() == 1) return ['campaign' => ['status' => FacebookHelper::CAMPAIGN_STATUS_ACTIVE]];
if($campaign->getFbCampaignId() == 2) return ['campaign' => ['status' => FacebookHelper::CAMPAIGN_STATUS_ACTIVE]];
if($campaign->getFbCampaignId() == 3) return ['campaign' => ['status' => FacebookHelper::CAMPAIGN_STATUS_ARCHIVED]];
}
)
);
您可以将此简化为
$statuses = [
1 => FacebookHelper::CAMPAIGN_STATUS_ACTIVE,
2 => FacebookHelper::CAMPAIGN_STATUS_ACTIVE,
3 => FacebookHelper::CAMPAIGN_STATUS_ARCHIVED,
];
$helper
->expects($this->exactly(count($statuses))
->method('getExternalCampaignData')
->willReturnCallback(function(Campaign $campaign) use ($statuses) {
$id = $campaign->getFbCampaignId();
if (!array_key_exists($id, $statuses)) {
return;
}
return [
'campaign' => [
'status' => $statuses[$id],
],
];
});
在闭包中,
$class
未定义。很抱歉,我更改了答案,但忘记编辑所有变量。谢谢通知,我刚改了。谢谢,很好的缩短版本。