8

我有各种 PHP 脚本,它们使用mysqli这套函数来访问数据库。我编写了这些脚本来处理各种错误情况(例如mysqli_stmt_execute返回 false)。

是否有一种简单的方法可以伪造这些错误条件以验证用户收到的输出是否适合这些条件?

4

4 回答 4

8

如果您使用的是 mysqli 类。

例如:

<?php
     $mysqli = new mysqli("localhost", "user", "password", "db");
     $query = "INSERT INTO some_table (some_field) VALUES ('some_vale')";
     $stmt = $mysqli->prepare($query);
     if (false === $stmt->execute()) {
         echo "Oops! some_value for same_field in some_table returned false";
     }

模拟类并覆盖语句执行。

<?php
    class my_mysqli extends mysqli
    {
        public function prepare ($query)
        {
            return new my_mysqli_stmt();
        }

    }

    class my_mysqli_stmt extends mysqli_stmt {
        public function execute ()
        {
            return false;
        }
    }

为了让每个执行方法都返回 false,您需要更改的是:

<?php
     $mysqli = new my_mysqli("localhost", "user", "password", "db");

如果您使用的是函数

例如:

<?php
     $mysqli = mysqli_connect("localhost", "user", "password", "db");
     $query = "INSERT INTO some_table (some_field) VALUES ('some_vale')";
     $stmt = mysqli_prepare($mysqli, $query);
     if (false === mysqli_stmt_execute($stmt)) {
         echo "Oops! some_value for same_field in some_table returned false";
     }

命名空间 php >= 5.3 中的猴子补丁

<?php
    namespace my_faking_namespace {
        function mysqli_stmt_execute($stmt) 
        {
            return false;    
        }

        $mysqli = mysqli_connect("localhost", "user", "password", "db");
        $query = "INSERT INTO some_table (some_field) VALUES ('some_vale')";
        $stmt = mysqli_prepare($mysqli, $query);
        if (false === mysqli_stmt_execute($stmt)) {
            echo "Oops! some_value for same_field in some_table returned false";
        }
    }

您的脚本将调用my_faking_namespace\mysqli_stmt_execute()而不是 php 版本。

注意:如果您调用函数,例如\mysqli_stmt_execute()此版本显式调用全局命名空间,这将不起作用。

不太容易的替代方案,用于完成目的

这些修改调用堆栈级别的函数,通过使用自定义扩展模块(需要安装)在内部更改 php。

  • 高级 PHP 调试器具有override_function()rename_function()
  • runkitrunkit_function_copy, runkit_function_redefine, runkit_function_remove,runkit_function_rename并且可以改变你想要的任何东西。

开心!

于 2012-08-26T06:32:45.890 回答
1

如果您正在寻找自动化测试,最好的方法(使用 PHP)是PHPUnit

使用 PHPUnit,您可以编写单元测试(尤其是断言),它允许您验证用户接收到的输出是否适合各种不同的条件。

于 2012-08-25T23:03:40.630 回答
0

如果您不在生产环境中,最好的方法是更改​​ PHP 中的各种数据库参数。

  • 更改数据库密码以查看您如何处理连接错误
  • 修改你的表结构,看看你如何处理查询错误
  • 尝试查看查询中的特殊字符(例如:буква)会发生什么情况
于 2012-07-27T12:16:50.790 回答
0

也许你问错了问题:为什么你的核心业务逻辑依赖于第三方库/API?你听说过所谓的洋葱架构吗?将您的应用程序更多地沿着这些线分层——域、业务、基础设施/测试——让您更轻松地测试不会改变的事物:您的业务逻辑。

然而,由于 PHP 是一种动态类型语言,所以 mocking 本质上是免费的。只要您使用的是面向对象特性而不是全局函数,您创建可测试代码所需要做的就是将假数据库句柄注入代码中。一个好方法是将$db参数添加到您的函数/方法中。像这样微不足道的事情:

function updateStuff($rowIds, $newValues, $db) { ... }

然后,在你覆盖的单元测试中updateStuff,传入一个模拟对象作为$db参数。

于 2012-08-26T06:53:21.380 回答