【问题标题】:Unittesting in PHP and SQLPHP 和 SQL 中的单元测试
【发布时间】:2017-01-26 16:43:32
【问题描述】:

我正在尝试使用 PHPUnit 为 PHP 项目编写单元测试。该项目主要使用 SQL 数据库。

我拥有的任何函数都使用 SQL,但我不知道如何开始编写测试。我很难找到要执行的测试,因为它们都与 SQL 一起工作,而且它们中的大多数不返回任何内容,而只是操纵数据库和会话变量。

这是创建测试的尝试之一:

    <?php
    require_once '../../test/admin/admin.php';

    class checkIsAdminTest extends PHPUnit_Framework_TestCase {
        private $ID = '123456789';
        private $Class = 0;
        private $Pass = 'Aa12345678';
        private $First = "Bla";
        private $Last = "Bla";
        private $Email = "bla@bla.bla";

        protected function setUp() {
            parent::setUp();

            $servername = "localhost";
            $username = "root";
            $password = "";

            $dbname = 'trivia';
            $conn = mysqli_connect($servername, $username, $password, $dbname);

            $sql = "INSERT INTO `users` (`ID`, `Class`, `Password`, `First`, `Last`, `Email`) VALUES ('" . $this->ID . "', '" . $this->Class . "', '" . sha1($this->Pass) . "', '" . $this->First . "', '" . $this->Last . "', '" . $this->Email . "');";
            mysqli_query($conn, $sql);

            session_start();
            $_SESSION["ID"] = $this->ID;
        }

        protected function tearDown() {
            parent::tearDown();
        }

        public function __construct() {
        }

        public function testCheckIsAdmin() {
            $this->assertEquals($this->Class == 0 ? False : True, checkIsAdmin());
        }
    }
?>

该函数检查名为“Users”的表中记录的“Class”字段的值为0或1,如果为1则返回“true”,否则返回false。

【问题讨论】:

    标签: php mysql unit-testing


    【解决方案1】:

    您遇到的这个问题表明您当前的设计存在更大的问题(“代码味道”),即您有一个混合了两个问题的类,即存储(mysql 的东西)和业务逻辑本身。这些应该是单独的关注点,因此是单独的类,您应该考虑如何解开这两个关注点(然后您应该使用Dependency Injection 将这两个关注点耦合在一起,通过将数据库对象传递给业务对象,例如构造函数参数)。

    一旦您设法将它们分开,您就可以将这两个模块单独组合起来。对于实现业务逻辑的类,您可以用mock object 替换 SQL 类,您可以在其中控制正在测试的对象接收的响应,而不必依赖可能具有或不具有正确数据的真实数据库在里面测试。

    单元测试的一个重要方面是,您必须能够将代码分成不同的单元,这些单元可以尽可能独立地进行测试。这需要您比平时更多地考虑应用程序的架构。这不仅具有可测试性的优势,还可以使您的代码更加灵活和适应性强。例如,如果您决定在数据库和业务对象之间添加一个缓存层怎么办?使用模块化代码,编写一个可以与数据库类以相同方式操作但维护自己的内部缓存的对象应该相对容易,如果请求的数据不在缓存中,则仅将请求传递给实际数据库。这对客户端类应该是不可见的。如果您决定用例如 Google Cloud 中的 BigTable 替换 MySQL,情况也是如此。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-05
      • 2023-03-31
      • 2013-05-26
      • 2015-02-09
      • 1970-01-01
      • 2015-11-17
      • 2020-09-03
      • 2017-10-26
      相关资源
      最近更新 更多