2014-01-23 3 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

정적 함수는 단위 테스트에서 좋지 않으므로 개인 메서드를 만들고 조롱하지 마십시오.

쿼리 팩토리를 만드는 것이 좋습니다. 이 기능은 코드를 주입하고 단위 테스트하는 기능을 제공 할뿐만 아니라 앞으로 Propel 대신 XYZ orm을 사용하려는 경우 더 쉽게 사용할 수 있습니다.

#

<?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. 를, 전자 개인 방법을 만듭니다. 지. "getQueryFindByPk"를 만든 다음 Contacts 클래스에서 조롱하여 필요한 것을 반환하십시오.
  2. 쿼리 인스턴스를 생성자에 전달하지만 이해할 수있는 것처럼 여러 쿼리 인스턴스를 가질 수 있습니다.
  3. 쿼리 인스턴스를 반환 할 수있는 QueryFactory, Repository 또는 QueryBuilder를 만듭니다.

다시 한번 말하지만 문제는 쿼리에 "하드"의존성이 있다는 것입니다.