class Connect
{
private $dbName;
public function __construct($dbName)
{
$this->dbName = $dbName;
}
public function getQuery()
{
return $this->dbName;
}
}
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');
}
}
class Member
{
private $connect;
public function __construct(ConnectFacade $connect)
{
$this->connect = $connect;
}
public function data()
{
return $this->connect->dbA->getQuery();
}
}
require 'vendor/autoload.php';
echo (new Member(new ConnectFacade))->data();
In my case, I have many tables from many databases need to be connected in one class, therefore I need to declare many connections with different connection name very often, so I put it to ConnectFacade
for saving time, I know it's kind of complicated, but that's the structure of my company, this sample code will show connect to database a
on index.php, of course in reality the connection is doing a lot of stuffs, my question is I don't know how mock on this situation, this is what I tried
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();
}
}
and I got Call to a member function getQuery() on a non-object in D:\www\phpunit\class\Member.php on line 14
, I don't know how to make the test pass.
The problem is that dbA
is not a method on ConnectFacade, but rather a variable. Therefore $connect->shouldReceive('dbA->getQuery')
won't work.
Instead you need to set the dbA
variable as a mock and then change the expectation to just receive 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);
}
Another option would be to instead mock the creation of the Connect class in ConnectFacade instead of mocking the whole 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);
}