【问题标题】:Mocking a Propel Query in a function (Symfony2)在函数中模拟 Propel 查询 (Symfony2)
【发布时间】:2014-01-23 10:01:39
【问题描述】:

我正在尝试为使用 Propel 查询的类编写单元测试(使用 phpunitmockery)。
如何模拟查询$contact = ClientContactQuery::create()->findPK($id);

我正在努力寻找任何例子。

我的班级;

<?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);
    }

}

【问题讨论】:

    标签: php unit-testing symfony phpunit propel


    【解决方案1】:

    静态函数不适合单元测试,请不要创建私有方法并模拟它。

    我强烈建议创建一个查询工厂。这不仅使您能够注入和单元测试您的代码,而且如果您将来想使用 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);
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      你真的不能嘲笑它,因为你对它有“硬”的依赖。因此,要解决这个问题,您应该考虑从 getContact 方法中移动对查询的“硬”依赖。

      你可以通过三种方式做到这一点:

      1. 创建您的私有方法,例如。 G。 “getQueryFindByPk”,然后在您的联系人类上模拟它,以返回您需要的内容。
      2. 将查询实例传递给构造函数,但据我了解,您可以有多个查询实例。
      3. 创建类似 QueryFactory、Repository 或 QueryBuilder 的东西,它们可以返回给您的查询实例。

      因此,问题再次在于对查询的“硬”依赖。

      【讨论】:

        猜你喜欢
        • 2023-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-13
        • 1970-01-01
        相关资源
        最近更新 更多