如何在其他 class 中模拟 class
How to mock class which within other class
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();
在我的例子中,我有许多来自许多数据库的表需要连接到一个 class,因此我需要经常声明许多具有不同连接名称的连接,所以我把它放在 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
,不知道怎么才能通过
问题是 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 class 的创建,而不是模拟整个 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);
}
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();
在我的例子中,我有许多来自许多数据库的表需要连接到一个 class,因此我需要经常声明许多具有不同连接名称的连接,所以我把它放在 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
,不知道怎么才能通过
问题是 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 class 的创建,而不是模拟整个 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);
}