【问题标题】:How can I improve unit testing this function如何改进单元测试此功能
【发布时间】:2016-05-01 22:24:09
【问题描述】:

我想知道是否有其他单元测试(我的意思是我可以在不依赖测试数据库的情况下执行的其他单元测试)可以为以下类中的函数 getAll 执行:

<?php
namespace Example\Model;

use Example\Lib\PdoConnection;

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('Example\Model\UserModel')
    ->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 函数才能模拟它?还是有另一种成本更低的方法来使其可测试?

欢迎所有建议。

谢谢

【问题讨论】:

  • 由于依赖注入,您应该将 pdo 连接作为构造函数参数传递。青少年通过模拟连接到伪造数据库操作的旅游模型。测试这个对象完全取决于数据库。因此,测试有效性的帖子将测试使用预期参数调用 pho 方法。那么这是一个外观,而不是一个模型。称之为 UserProviderFacade
  • 你不应该模拟你的数据库抽象层。与其编写单元测试,不如编写一个可以访问数据库的集成测试。 mockobjects.com/2007/04/test-smell-everything-is-mocked.html
  • @Pherserk,已经过去几天了,我发现您的回答很有道理,您可以将其添加为答案以便我接受吗?

标签: php unit-testing phpunit


【解决方案1】:

由于依赖注入,您应该将 pdo 连接作为构造函数参数传递。然后您可以考虑模拟连接并确保使用预期参数调用预期方法。您可以使用 Mockery、Prophecy 或 phpunit 模拟对象等库。那么这不是一个模型,而是一个提供者或存储库。所以你应该称它为 UserProvider 或 UserRepository

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-16
    • 2020-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多