Using PHPUnit does not mean that you can test any source code. You should have designed your classes to be easy to test. Also, there are places where you can not put them into Unit test even if you have designed that way. If you can not put in the Unit test, you must divide it. Rather, how much code can I put in a unit test?
Unit test here refers to “method-only test” and “class-only test”.
object
setting value
external system(DB, API, file, command)
We separate those “dense dependencies” and “design the class”, “implement the class” and “make a test of the class”. “Dense dependence” refers to, for example the following.
The method using the object directly news the object(depends on the object)
Directly reference configuration files(file_get_contents, json_decode) in logic(depends on file system)
Where file(file_put_contents) directly in logic(depends on file system)
Peek directly into DB(mysqli, PDO) in logic(depends on network and database)
Direct API(file_get_contents, curl) in logic(depends on network and API)
Hit command(system) directly in logic(depends on OS)
namespace UnitTest\Sample;
class Hoge {
protected $settings = null;
protected $fileManager = null;
protected $dbManager = null;
protected $apiManger = null;
protected $commandManager = null;
public function __construct (
$settings,
$fileManager,
$dbManager,
$apiManager,
$commandManager){
$this->settings = $settings;
$this->fileManager = $fileManager;
$this->dbManager = $dbManager;
$this->apiManager = $apiManager;
$this->commandManager = $commandManager;
}
}
namespace UnitTest\Sample;
class DatabaseSession
{
private $connection = null;
public function __construct($connection)
{
$this->connection = $connection;
}
public function save($tableName, $object)
{
if(!$tableName || !is_scalar($tableName)|| !$object){
throw new \InvalidArgumentException('$tableName or $object is empty or invalid type');
}
if(is_object($object) && $object instanceof \stdClass){
$ojbect = (array)$object;
}
if(!is_array($object)){
throw new \InvalidArgumentException('$object must be array or \stdClass');
}
$values = array_values($object);
$tableName = '`' . str_replace('`', '\\`', $tableName).'`';
$columnBlock = implode(',', array_map(function($col) {return '`' . str_replace('`', '\\`', $col) . '`';}, array_keys($object)));
$valueBlock = implode(',', array_map(function($val) {return '?'; }, $values));
$valueMarker = implode('', array_map(function($val) {return strval(intval($val)) === strval($val) ? 'i' : 's'; }, $values));
$stmt = $this->connection->prepare("REPLACE INTO $tableName ($columnBlock) VALUES ($valueBlock);");
array_unshift($values, $valueMarker);
$pointer = array();
foreach($values as $key => $val){
$pointer[$key] = &$val;
}
call_user_func_array(array($stmt, 'bind_param'), $pointer);
$stmt->execute();
$stmt->close();
}
}