Testing coverage with PHPUnit and PDO

帅比萌擦擦* 提交于 2019-12-12 10:27:46

问题


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

  1. Assume that if the prepare has worked, that the execute will as well, but not particularly happy with that.
  2. 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!