我对TDD非常陌生。我正在使用phpunit 7.4x-dev。我有下面的抽象类,我正在尝试为其开发单元测试。
use PDO;
abstract class Model {
protected static function getDB() {
static $db = null;
if ($db === null) {
$db = new PDO(ConfigDatabase::DSN, ConfigDatabase::USER, ConfigDatabase::PASSWORD);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
return $db;
}
}
我创建了以下测试来解决需要处理静态保护方法的问题。如果我提供“ ConfigureDatabase”类,它将起作用。
use PHPUnit\Framework\TestCase;
class ModelTest extends TestCase {
function newMockClass(){
$stub = new class() extends Model{
function getStaticMethod($methodName){
return self::$methodName();
}
};
return $stub;
}
public function testDatabaseExists() {
$stub = $this->newMockClass();
$db = $stub->getStaticMethod('getDB');
$this->assertInstanceOf(PDO::class,$db);
}
}
由于我不想我的测试依赖于任何实际的数据库,因此我该如何伪造对PDO的调用。
答案 0 :(得分:0)
按照Dormilich的建议,我开发了一个数据库接口,以防万一我以后决定不使用PDO。
interface CRUDImp {
function __construct($datbaseBridgeLikePDO);
...
}
接下来,我为构造函数编写了测试。我使用设置来确保我从全新的\ PDO模拟开始。
class PDOWrapperTest extends TestCase {
private $pdoMock;
private $db;
function setup() {
$this->pdoMock = $this->createMock('\PDO');
$this->db = new PDOWrapper($this->pdoMock);
}
public function testWrapperExists() {
$this->pdoMock->method('getAttribute')->willReturn(\PDO::ERRMODE_EXCEPTION);
$db = new PDOWrapper($this->pdoMock);
$x = $db instanceof CRUDImp;
$this->assertTrue($x);
}
/**
* @expectedException \Exception
*/
public function testNonPDOPassedToConstructor() {
$mock = $this->createMock('\Exception');
$x = new PDOWrapper($mock);
}
...
}
由于PHP是松散类型的,所以我检查以确保传递给构造函数的类是\ PDO的实例。我按如下方式实现了具体的课程
class PDOWrapper implements CRUDImp {
private $pdo;
private $dataOutputType = \PDO::FETCH_ASSOC;
public function __construct($pdo) {
if (!($pdo instanceof \PDO)) {
throw new \Exception("PDOWrapper must be passed instance of \PDO");
}
$attr_Errmode = $pdo->getAttribute(\PDO::ATTR_ERRMODE);
if ($attr_Errmode !== \PDO::ERRMODE_EXCEPTION) {
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
}
$this->pdo = $pdo;
}
...
}
现在,我有了一个独立的数据库包装程序,原始的Model测试现在变得微不足道了,不再需要了。对抽象类Model的修改如下:
abstract class Model {
protected $database=null;
function __construct(CRUDWrapper $database) {
$this->database = $database;
}
...
}
对于那些不熟悉依赖注入的人,我发现以下链接很有帮助:
http://php-di.org/doc/understanding-di.html https://codeinphp.github.io/post/dependency-injection-in-php/ https://designpatternsphp.readthedocs.io/en/latest/Structural/DependencyInjection/README.html
希望这会缩短某人的工作时间。