2014-01-23 100 views
2

我正在嘗試爲使用Propel查詢的類編寫單元測試(使用phpunitmockery)。
如何模擬查詢$contact = ClientContactQuery::create()->findPK($id);嘲笑函數中的Propel查詢(Symfony2)

我很努力地找到任何這方面的例子。

我的班級;

<?php 
namespace MyBundle\Classes; 

use MyBundle\Model\ClientContactQuery; 
use MyBundle\Model\ClientContact; 

class Contacts { 

    protected $_cache; 

    public function __construct($cache) 
    { 
     $this->_cache = $cache; 
    } 

    public function getContact($id) 
    { 
     $contact = ClientContactQuery::create()->findPK($id); 

     if (! $contact) { 
      throw new NotFoundHttpException('Client contact not found.'); 
     } 

     return $contact; 
    } 

} 

到目前爲止我的測試用例;

<?php 
namespace MyBundle\Tests\Classes; 

use Mockery as m; 
use MyBundle\Classes\Contacts as c; 

class ContactsTest extends \PHPUnit_Framework_TestCase 
{ 
    public function tearDown() 
    { 
     m::close(); 
    } 

    public function testGetValidContact() 
    { 
     // Arrange 
     $cache = m::mock('cache'); 

     // Act 
     $contact = new c($cache); 
     // am lost at this point :-(

     // Assert 
     $this->assertInstanceOf('MyBundle\Classes\Contacts', $contact); 
    } 

} 

回答

4

靜態函數對單元測試不太好,請不要創建私有方法並模擬它。

我強烈建議創建一個查詢工廠。這不僅會讓你有能力注入並單元測試你的代碼,但是如果你想在將來使用XYZ orm代替Propel,它將使生活更輕鬆。

<?php 
namespace MyBundle\Classes; 

use MyBundle\Model\ClientContactQuery; 
use MyBundle\Model\ClientContact; 

class Contacts { 

    protected $_cache; 

    /** @var QueryFactory */ 
    private $queryFactory; 


    public function __construct($cache, QueryFactory $queryFactory) { 
     $this->_cache = $cache; 
     $this->queryFactory = $queryFactory; 
    } 

    public function getContact($id) { 
     $contact = $this->queryFactory->newClientContactQuery()->findPK($id); 

     if (! $contact) { 
      throw new NotFoundHttpException('Client contact not found.'); 
     } 

     return $contact; 
    } 

} 

<?php 
class QueryFactory { 

    const CLASS_NAME = __CLASS__; 

    public function newClientContactQuery() { 
     return ClientContactQuery::create(); 
    } 

    public function newSomeOtherQuery() { 
     return SomeOtherQuery::create(); 
    } 

} 

<?php 
namespace MyBundle\Tests\Classes; 

use Mockery as m; 
use MyBundle\Classes\Contacts as c; 

class ContactsTest extends \PHPUnit_Framework_TestCase { 
    public function tearDown() { 
     m::close(); 
    } 

    public function testGetValidContact() { 
     $cache    = m::mock('cache'); 
     $queryFactory  = m::mock(QueryFactory::CLASS_NAME); 
     $clientContactQuery = m::mock('ClientContanctQuery'); 

     $contact = new c($cache, $queryFactory); 

     $queryFactory->shouldReceive('newClientContactQuery')->with()->once()->andReturn($clientContactQuery); 
     $clientContactQuery->shouldReceive('findPK')->with('myTestInputId')->once->andReturn('something?'); 

     $this->assertInstanceOf('MyBundle\Classes\Contacts', $contact); 
    } 

} 
1

你真的不能嘲笑它,因爲你對它有「硬」依賴性。所以,要解決這個問題,你應該考慮從getContact方法的查詢中移動「硬」依賴。

你可以做到這一點的方法有三種:

  1. 創建您的私有方法,E。 G。 「getQueryFindByPk」,然後在你的Contacts類中模擬它,以返回你所需要的。
  2. 將查詢實例傳遞給構造函數,但據我所知,可以有多個查詢實例。
  3. 創建類似於QueryFactory,Repository或QueryBuilder,它可以返回給你的查詢實例。

所以,再一次,問題是對查詢具有「硬」依賴性。