如何模拟其他类中的类

时间:2016-02-03 09:21:30

标签: phpunit mockery

Connect.php

class Connect
{
    private $dbName;

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

    public function getQuery()
    {
        return $this->dbName;
    }
}

ConnectFacade.php

class ConnectFacade
{
    public $dbA;
    public $dbB;
    public $dbC;
    public $dbD;

    public function __construct()
    {
        $this->dbA = new Connect('connect to database a');
        $this->dbB = new Connect('connect to database b');
        $this->dbC = new Connect('connect to database c');
        $this->dbD = new Connect('connect to database d');
    }
}

Member.php

class Member
{
    private $connect;

    public function __construct(ConnectFacade $connect)
    {
        $this->connect = $connect;
    }

    public function data()
    {
        return $this->connect->dbA->getQuery();
    }
}

的index.php

require 'vendor/autoload.php';

echo (new Member(new ConnectFacade))->data();

在我的情况下,我需要在一个类中连接许多数据库中的许多表,因此我需要经常声明许多具有不同连接名称的连接,因此我将其放到ConnectFacade以节省时间,我知道它有点复杂,但这是我公司的结构,这个示例代码将在index.php上显示connect to database a,当然实际上连接正在做很多事情,我的问题是我不知道如何嘲笑这种情况,这就是我试过的

use Mockery as m;

class MemberTest extends PHPUnit_Framework_TestCase
{
    public function testData()
    {
        $connect = m::mock('ConnectFacade');
        $connect->shouldReceive('dbA->getQuery')
            ->once()
            ->andReturn(true);
        $actual = (new Member($connect))->data();
        $this->assertTrue($actual);
    }

    public function tearDown()
    {
        m::close();
    }
}

我得到Call to a member function getQuery() on a non-object in D:\www\phpunit\class\Member.php on line 14,我不知道如何让测试通过。

1 个答案:

答案 0 :(得分:1)

问题是dbA不是ConnectFacade上的方法,而是变量。因此$connect->shouldReceive('dbA->getQuery')无法工作。

相反,您需要将dbA变量设置为模拟,然后将期望更改为仅接收getQuery

public function testData()
{
    $connect = m::mock('ConnectFacade');
    $connect->dbA = $connect;
    $connect->shouldReceive('getQuery')
        ->once()
        ->andReturn(true);
    $actual = (new Member($connect))->data();
    $this->assertTrue($actual);
}

另一种选择是在ConnectFacade中模拟Connect类的创建,而不是模拟整个ConnectFacade:

public function testData()
{
    $connect = m::mock('overload:Connect');
    $connect->shouldReceive('getQuery')
        ->once()
        ->andReturn(true);
    $connectFacade = new ConnectFacade;
    $actual = (new Member($connectFacade))->data();
    $this->assertTrue($actual);
}