问题
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;
}
}
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.
My test is...
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 );
}
}
There are two possibilities I can think of
- Assume that if the prepare has worked, that the execute will as well, but not particularly happy with that.
- Somehow override the connection to make it fail in a controlled way.
回答1:
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());
}
}
来源:https://stackoverflow.com/questions/46379109/testing-coverage-with-phpunit-and-pdo