如何用PHPUnit测试含exit的WordPress重定向函数?
解决WordPress插件重定向测试中的Headers Already Sent错误
问题分析
你遇到的错误根源有两个:一是测试环境的bootstrap.php第265行已经输出了内容(比如调试信息、标签前后的空格/换行),而wp_redirect()要求HTTP头必须在任何输出之前发送,两者冲突导致报错;二是原函数里的exit会直接终止测试脚本,让assertRedirect()根本没机会执行。
解决步骤
1. 清除提前输出
打开/Applications/MAMP/htdocs/wordpress/wp-content/plugins/xyz_woocommerce/tests/phpunit/includes/bootstrap.php,定位到第265行:
- 如果是
echo/print这类调试输出,直接删除或注释 - 如果是
<?php标签前后的空格、换行,清理掉这些多余字符 - 如果是其他代码产生的输出,调整逻辑确保测试执行前没有任何内容输出
2. 修改测试函数,适配重定向与exit逻辑
原测试直接调用redirectUser()会触发exit中断测试,需要用PHPUnit机制捕获exit,同时验证wp_redirect的调用正确性。修改后的测试代码示例:
public function testRedirectUser() { $order = wc_create_order(); $url = 'http://www.example.com'; // 模拟get_return_url返回指定URL $this->instance->shouldReceive('get_return_url') ->with($order) ->andReturn($url); // 捕获exit操作,避免终止测试 $this->expectExit(); // 调用重定向方法 $this->instance->redirectUser($order); // 验证wp_redirect是否以正确参数被调用 $this->assertSame($url, wp_get_referer() ?: $url); }
如果使用WP_Mock框架,可更精准模拟wp_redirect:
public function testRedirectUser() { $order = wc_create_order(); $url = 'http://www.example.com'; $this->instance->shouldReceive('get_return_url') ->with($order) ->andReturn($url); // 模拟wp_redirect被调用1次,参数为指定URL WP_Mock::userFunction('wp_redirect', [ 'args' => [$url], 'times' => 1, 'return' => true ]); // 捕获exit $this->expectExit(); $this->instance->redirectUser($order); }
额外提示
- 确保测试类继承自
WP_UnitTestCase,才能使用WordPress测试框架的专属方法 - 若
expectExit()方法不存在,可手动注册 shutdown 函数捕获exit:register_shutdown_function(function() { $last_error = error_get_last(); if ($last_error && strpos($last_error['message'], 'exit') !== false) { // 拦截exit,不中断测试流程 return; } });
内容的提问来源于stack exchange,提问作者Garima Prachi
相关产品推荐
相关产品推荐

