Как улучшить модульное тестирование этой функции

Я хочу знать, есть ли другие модульные тесты (я имею в виду другие модульные тесты, которые я могу сделать, не полагаясь на тестовую базу данных), которые я могу сделать для функции getAll в следующем классе:

<?php
namespace ExampleModel;

use ExampleLibPdoConnection;

class UserModel {

    private $pdoConn;

    function __construct()
    {
        $this->pdoConn = PdoConnection::getInstance();
    }

    function getAll()
    {
        $arrUsers = array();
        $strSql = "SELECT id, first_name, last_name FROM user";
        $arrData = array();
        try
        {
            $objRes = $this->pdoConn->prepare($strSql);
            $objRes->execute($arrData);
            $objRes->setFetchMode(PDO::FETCH_ASSOC);
            $arrUsers = $objRes->fetchAll();
        }
        catch(PDOException $e) {
            error_log($e->getMessage());
        }
        return $arrUsers;
    }   

Вот как я это тестирую:

function testGetAll()
{   
    $stubUserModel = $this->getMockBuilder('ExampleModelUserModel')
    ->disableOriginalConstructor()
    ->getMock();

    $stubUserModel->method('getAll')
    ->willReturn(array(array('id' => 1, 'first_name' => 'First1', 'last_name' => 'Last1'), array('id' => 2, 'first_name' => 'First2', 'last_name' => 'Last2')));

    $this->assertEquals(array(array('id' => 1, 'first_name' => 'First1', 'last_name' => 'Last1'), array('id' => 2, 'first_name' => 'First2', 'last_name' => 'Last2')), $stubUserModel->getAll());       
}

Я знаю, что он нуждается в большем количестве тестов, чтобы считаться хорошо юнит-тестом, и что тест, который я написал выше, бесполезен.

Я нахожу его трудным для тестирования, потому что он зависит от класса PDOConnection, а также класса, возвращаемого подготовленным оператором (экземпляр obj в этом примере является $objResult). Означает ли это, что я должен рефакторировать код и переместить зависимость PDOConnection за пределы этой функции и, возможно, передать $objRes как и аргумент, чтобы getAll функция могла издеваться над ней? или есть другой способ, который дешевле сделать его тестируемым?

Все предложения приветствуются.

Спасибо

1 ответ

  1. В связи с внедрением зависимостей необходимо передать соединение pdo в качестве параметра конструктора. Затем можно рассмотреть возможность макетирования соединения и убедиться, что ожидаемые методы вызываются ожидаемое время с ожидаемыми параметрами. Вы можете использовать библиотеки, такие как Mockery, Prophecy или PHPUnit mock objects. Тогда это не модель, а поставщик или репозиторий. Поэтому вы должны называть его UserProvider или UserRepository