直接测试 paginate() 易失败因依赖 $_GET 或数据库等外部状态;应拆分为纯函数,接收 $total、$page、$per_page 并返回分页数组,再通过边界值测试验证修正逻辑与布尔标志。

为什么直接测试 paginate() 函数容易失败
因为多数 PHP 分页函数(比如基于 array_slice() 或 SQL LIMIT 的封装)依赖外部状态:当前页码、总记录数、每页条数,甚至 $_GET 参数。若函数内部硬编码读取 $_GET['page'] 或直接拼接 SQL,就无法隔离测试——你改不了输入,也控制不了数据库返回。
实操建议:
- 把分页逻辑拆成纯函数:接收
$total、$page、$per_page三个参数,返回包含current、last、offset、limit的数组 - 避免在函数里访问超全局变量或执行查询;数据库分页应由调用方传入结果集或总条数
- 如果已有旧函数不可改,用
$_GET模拟需配合parse_str()+$_SERVER['QUERY_STRING']临时覆盖,但不推荐
怎么写可断言的测试用例(以 PHPUnit 为例)
核心是验证输出结构和数值边界是否符合预期,而不是渲染 HTML。
例如一个简化版 calculatePagination():
function calculatePagination(int $total, int $page = 1, int $per_page = 10): array
{
$last = (int) ceil($total / $per_page);
$page = max(1, min($page, $last));
$offset = ($page - 1) * $per_page;
<pre class="brush:php;toolbar:false;">return [
'current' => $page,
'last' => $last ?: 1,
'offset' => $offset,
'limit' => $per_page,
'has_prev' => $page > 1,
'has_next' => $page <p>}</p>对应测试要点:
- 测试
$page = 0→ 应被纠正为1,current和offset都得对 - 测试
$page > $last(如总 25 条、每页 10、请求第 5 页)→current应为3,不是崩溃或返回负 offset - 测试
$total = 0→last应为1,避免除零或 ceil(0) 异常 - 检查
has_prev/has_next布尔值是否随页码正确翻转
如何模拟数据库层做集成验证
单元测试不碰 DB,但你可能想确认“用这个 offset+limit 查出来的数据量是否匹配分页元信息”。这时要 mock 查询行为,而非连真实库。
做法:
- 把数据获取抽成接口,如
PaginatorInterface::fetchPage(int $offset, int $limit): array - 在测试中注入一个 fake 实现,返回预设数组(比如 12 条记录),再调用你的分页函数算出
offset和limit,最后 assert 返回数组长度等于min($per_page, 剩余条数) - 不要在测试里写
new PDO(...)或执行真实 SQL —— 速度慢、依赖环境、易因数据变动失败
错误示范:$result = $pdo->query("SELECT * FROM users LIMIT {$offset},{$limit}")->fetchAll(); —— 这已经不是单元测试了。
容易被忽略的边界:中文 URL、负数页码、超大页码
用户可能手动改 URL 传 ?page=-1、?page=9999999 或 ?page=一二三。PHP 默认会把非数字字符串转成 0,而 (int) "abc" 是 0,(int) "-1" 是 -1 —— 这些都得进你的校验逻辑。
建议在调用 calculatePagination() 前统一处理输入:
- 用
filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT, ['options' => ['default' => 1, 'min_range' => 1]])提前过滤 - 或者让分页函数自己做
max(1, (int) $page),但必须明确文档说明它会静默修正 - 日志里记下被修正的页码(如
warning: page=-5 corrected to 1),方便排查前端传参错误
没做这步,线上就可能出现第 1 页显示空数据、或直接 500 错误——而单元测试里恰恰最容易漏掉这类“非法输入”分支。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











