我想为我的申请做一些单元测试。这是我第一次使用PHPUnit进行管理(以及更多的单元测试),我希望得到一些建议。
首先,让我们说我有这个班级
class LodgingManager
{
private $session;
private $entity_manager;
public function __construct(Session $session, EntityManager $em)
{
$this->session = $session;
$this->entity_manager = $em;
}
public function loadLodgingList()
{
//If I've already fetched lodgings from db, use the session one.
//Everytime a lodging is added, session is refreshed
$lodging_list = $this->session->get('lodging_list');
if (!$lodging_list) {
$lodging_repo = $this->entity_manager->getRepository('KoobiBookingEngineBundle:Lodging');
$lodging_list = $lodging_repo->getAllForList();
$this->session->set('lodging_list', $lodging_list);
}
return $lodging_list;
}
[...]
}
这是一个简单而愚蠢的方法,但是从这里开始对我来说似乎非常有用,因为代码并不是很复杂。每个人都可以看到我使用自定义DQL方法来帮助我检索一些实体并将它们放入会话中。
我已经创建了一个包含一些虚拟数据的测试数据库,我会测试它们。
据我所知,Doctrine的EntityManager有一个受保护的__construct()
方法。这意味着您无法使用"真实" EntityManager但你需要使用模拟的。可以对Repository等进行相同的考虑。
所以我生产的代码如下
class LodgingManagerTest extends \PHPUnit_Framework_TestCase
{
const LODGING_CLASS = 'KoobiBookingEngineBundle:Lodging';
/** @var LodgingManager */
protected $lodging_manager;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $em;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $repository;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $session;
public function setUp()
{
$lodging_array_collection = new ArrayCollection();
$lodging = $this->getMock('Koobi\BookingEngineBundle\Entity\Lodging');
$lodging_array_collection->add($lodging);
$repository = $this->getMockBuilder('Koobi\BookingEngineBundle\Repository\LodgingRepository')
->disableOriginalconstructor()
->getMock();
$repository->expects($this->once())
->method('getAllForList')
->will($this->returnValue($lodging_array_collection));
$this->repository = $repository;
$em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
->disableOriginalconstructor()
->getMock();
$em->expects($this->once())
->method('getRepository')
->with($this->equalTo(static::LODGING_CLASS))
->will($this->returnValue($repository));
$this->em = $em;
$this->session = new Session(new MockArraySessionStorage());
$this->lodging_manager = $this->createLodgingManager($this->session, $this->em);
}
public function testLoadLodgingList()
{
$lodging_list = $this->lodging_manager->loadLodgingList();
$this->assertCount(1, $lodging_list);
}
}
每个测试对象都是一个模拟的对象(除了Lodging是一个"真正的"一个)。但对我来说,这个测试是无用的,因为我无法从数据库加载真实实体。
我完全知道这种测试很愚蠢,但我可以很容易地想象出其他需要真实对象的复杂测试。
那么,向专家用户询问您的意见是什么?我该如何进行更加相关和适当的测试呢?
答案 0 :(得分:2)
你应该重构代码,将“简单,愚蠢”的dao与其他东西分开(会话管理和业务逻辑)。然后将你的测试分为2组或3组。
单元测试:与环境(也来自数据库)隔离测试组件。在这个测试中,你模拟你的数据库(entityManager,存储库,但它在你的技术中调用),你检查是否按预期调用这些模拟
数据库测试:您使用真实 entityManager,存储库和mysql / oracle /以测试您的sql / orm代码是否正常工作。您只测试数据库代码而没有任何业务逻辑或会话管理
端到端测试。您启动整个应用程序并模拟用户单击Web界面
答案 1 :(得分:1)
恕我直言,你应该这样做:
希望这个帮助