问题描述
作为练习,我正在尝试使用PHPUnit达到100%的代码覆盖率,这几乎可以实现,但这是我发现很难的错误位.
As an exercise, I'm trying to reach 100% code coverage using PHPUnit, this is almost there, but it's the error bits which I've found difficult.
我有一个示例类,与真实代码有类似的问题,确切的代码不是问题,但是行为是相同的.
I have an example class which I has a similar issue to my real code, the exact code is not the issue, but the behaviour is the same.
class DBAccess {
private $db;
public function __construct( \PDO $db ) {
$this->db = $db;
}
public function select () {
$data = false;
if ( $stmt = $this->db->prepare("select * from user") ){
if ( $stmt->execute() ){
$data = $stmt->fetchAll();
}
else {
echo "Something went wrong"; // How to get here!
}
}
return $data;
}
}
这是停止100%覆盖率的一行.困难在于我需要准备通过,但执行失败.我已经通过将无效的外键或字段传递给表的大号来进行更新,但是通过选择,我不确定会出什么问题.
It's the one line which is stopping the 100% coverage. The difficulty is that I need the prepare to pass, but the execute to fail. I've managed this on updates by passing invalid foreign keys or fields to large for the table, but with a select, I'm not sure what can go wrong.
我的测试是...
class DBAccessTest extends TestCase {
private $pdo;
public function setUp() {
$this->pdo = new PDO("mysql:host=172.18.0.2;dbname=test",
"test", "RkqwD1gjOdjkrwTt");
$this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
}
public function testSelect() {
$test = new DBAccess( $this->pdo );
$this->assertTrue($test->select() != false );
}
}
我可以想到两种可能性
- 假设如果准备工作成功了,那么执行者也会这样做,但对此并不特别满意.
- 以某种方式覆盖连接以使其以可控的方式失败.
推荐答案
这正是 PHPUnit的测试双打适用于.还有以面向对象的方式设计类的荣誉,因此很容易将模拟注入到它们中.
This is exactly what PHPUnit's test doubles are for. And kudos for designing your classes in an object oriented way, so it's easy to inject mocks into them.
<?php
use PHPUnit\Framework\TestCase;
class DBAccessTest extends TestCase
{
public function test_something_goes_wrong()
{
// Create test doubles.
$stmtMock = $this->createMock(\PDOStatement::class);
$pdoMock = $this->createMock(\PDO::class);
// Configure the stubs.
$stmtMock->method('execute')
->willReturn(false);
$pdoMock->method('prepare')
->willReturn($stmtMock);
// Inject the mock.
$test = new DBAccess($pdoMock);
// Assert.
$this->assertFalse($test->select());
}
}
这篇关于使用PHPUnit和PDO测试覆盖率的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!