【发布时间】:2015-04-24 07:55:14
【问题描述】:
我对 symfony 还是很陌生,真的很喜欢它。
我正处于创建和设置服务的阶段,服务本身使用 2 个依赖项:
- 返回 json 数据的数据 API(这是一个单独的库, 我已经实现为服务并附带了自己的单元测试)。
- Doctrine Entity Manager。
服务使用api提取所需的数据,然后循环遍历数据并检查数据是否已经存在,如果存在则更新现有实体并将其持久化,否则它会创建一个新实体分配数据并坚持下去。
我现在需要为此编写一个单元测试,我没有只使用 symfony2 教程中的 PHPUnit,这些教程正在测试来自控制器的响应。
我该如何为此服务编写单元测试? 特别是模拟我通常会从 api 中提取的数据。 然后检查该条目是否需要更新或创建?
一个代码示例将非常有帮助,因此我可以将其用作模板来为我创建的其他类似服务创建测试。
这是我要测试的服务:
<?php
namespace FantasyPro\DataBundle\DataManager;
use Doctrine\ORM\EntityManager;
use FantasyDataAPI\Client;
use FantasyPro\DataBundle\Entity\Stadium;
class StadiumParser {
/**
* @var EntityManager $em
*/
private $em;
/**
* @var Client $client
*/
private $client;
public function __construct( EntityManager $em, Client $client) {
$this->em = $em;
$this->client = $client;
}
/**
* @return array
*/
public Function parseData(){
//var_dump($this);
$stadiumData = $this->client->Stadiums();
//var_dump($stadiumData);
//get the Repo
$repo = $this->em->getRepository('DataBundle:Stadium');
$log = array();
foreach ($stadiumData as $stadium) {
// Get the current stadium in the list from the database
$criteria = array( 'stadiumID' => $stadium['StadiumID'] );
$currentStadium = $repo->FindOneBy( $criteria );
if ( ! $currentStadium) {
$currentStadium = new Stadium(); //no stadium with the StadiumID exists so create a new stadium
$logData = [
'action' => 'Added Stadium',
'itemID' => $stadium['StadiumID'],
'itemName' => $stadium['Name']
];
$log[] = $logData;
} else {
$logData = [
'action' => 'Updated Stadium',
'itemID' => $stadium['StadiumID'],
'itemName' => $stadium['Name']
];
$log[] = $logData;
}
$currentStadium->setStadiumID( $stadium['StadiumID'] );
$currentStadium->setName( $stadium['Name'] );
$currentStadium->setCity( $stadium['City'] );
$currentStadium->setState( $stadium['State'] );
$currentStadium->setCountry( $stadium['Country'] );
$currentStadium->setCapacity( $stadium['Capacity'] );
$currentStadium->setPlayingSurface( $stadium['PlayingSurface'] );
$this->em->persist( $currentStadium );
}
$this->em->flush();
return $log;
}
}
****** 更新 ******* 在阅读了 ilpaijin 的回答之后。
我已经简化了服务,所以它不再返回日志,我最初有这个,所以我可以通过将日志发送到我的控制器中的树枝模板来检查添加的内容,我最终计划让它运行为一个命令,以便我可以通过 cron 作业运行它,因此不需要日志位。
我现在在我的构造中设置实体,因为我不知道如何将实体作为注入的依赖项传递。
现在使用createNewStadium() 方法抓取一个新实体。
更新的服务:
namespace FantasyPro\DataBundle\DataManager;
use Doctrine\ORM\EntityManager;
use FantasyDataAPI\Client;
use FantasyPro\DataBundle\Entity\Stadium;
class StadiumParser {
/**
* @var EntityManager $em
*/
private $em;
/**
* @var Client $client
*/
private $client;
/**
* @var Stadium Stadium
*/
private $stadium;
public function __construct( EntityManager $em, Client $client) {
$this->em = $em;
$this->client = $client;
}
/**
* Gets a list of stadiums using $this->client->Stadiums.
* loops through returned stadiums and persists them
* when loop has finished flush them to the db
*/
public Function parseData(){
$data = $this->client->Stadiums();
//get the Repo
$repo = $this->em->getRepository('DataBundle:Stadium');
foreach ($data as $item) {
// Get the current stadium in the list
$criteria = array( 'stadiumID' => $item['StadiumID'] );
$currentStadium = $repo->FindOneBy( $criteria );
if ( ! $currentStadium) {
$currentStadium = $this->createNewStadium; //no stadium with the StadiumID use the new stadium entity
}
$currentStadium->setStadiumID( $item['StadiumID'] );
$currentStadium->setName( $item['Name'] );
$currentStadium->setCity( $item['City'] );
$currentStadium->setState( $item['State'] );
$currentStadium->setCountry( $item['Country'] );
$currentStadium->setCapacity( $item['Capacity'] );
$currentStadium->setPlayingSurface( $item['PlayingSurface'] );
$this->em->persist( $currentStadium );
}
$this->em->flush();
}
// Adding this new method gives you the ability to mock this dependency when testing
private function createNewStadium()
{
return new Stadium();
}
}
【问题讨论】:
-
Services 只不过是一个简单的类,你应该和一个简单的 PHP 类有同样的方法。
class StadiumParserTest extends PHPUnit_Framework_TestCase {}模拟 em,客户端并测试您的parseData。 -
这是我不知道该怎么做的嘲弄,我应该创建静态 JSON 文件并传递这些文件而不是从 api 获取数据吗?来自 api 的数据可能会随着时间的推移而变化,尽管它返回的数据始终具有相同的类型,但值可能会有所不同。
标签: symfony testing service phpunit