如何在PHPUnit+Selenium测试平台获取AJAX请求状态码与响应数据
在PHPUnit+Selenium中捕获AJAX请求的状态码与响应数据
Selenium WebDriver本身并没有提供直接监听网络请求的API,不过好在Chrome浏览器支持Chrome DevTools Protocol (CDP),我们可以通过它来捕获AJAX请求的状态码、响应头和响应体。结合你给出的代码片段,我整理了完整的实现方案:
核心思路
我们需要借助CDP的网络监控能力:
- 启用网络监听,捕获所有HTTP/HTTPS响应
- 筛选出目标AJAX请求(比如登录接口)
- 提取状态码、响应数据并用于测试断言
完整代码示例
use Facebook\WebDriver\Remote\RemoteWebDriver; use Facebook\WebDriver\Remote\WebDriverCapabilityType; use Facebook\WebDriver\WebDriverBy; class LoginAJAXTest extends \PHPUnit\Framework\TestCase { protected $webDriver; protected $ajaxResponses = []; protected function setUp(): void { // 配置Chrome驱动能力,兼容新版ChromeDriver的跨域限制 $capabilities = [ WebDriverCapabilityType::BROWSER_NAME => 'chrome', 'goog:chromeOptions' => ['args' => ['--remote-allow-origins=*']] ]; // 初始化远程WebDriver $this->webDriver = RemoteWebDriver::create('http://localhost:4444/wd/hub', $capabilities); // 启用CDP网络监控 $this->webDriver->executeCdpCommand('Network.enable', []); // 注册响应监听事件,捕获目标AJAX请求 $this->webDriver->executeCdpCommand('Network.responseReceived', [], function ($response) { $responseDetails = $response['params']['response']; // 这里根据你的AJAX接口URL进行筛选,比如/login接口 if (strpos($responseDetails['url'], '/api/login') !== false) { // 获取响应体内容 $responseBody = $this->webDriver->executeCdpCommand( 'Network.getResponseBody', ['requestId' => $response['params']['requestId']] )['body']; $this->ajaxResponses[] = [ 'url' => $responseDetails['url'], 'status_code' => $responseDetails['status'], 'headers' => $responseDetails['headers'], 'response_body' => $responseBody ]; } }); } public function testLoginAJAXResponse() { // 打开登录页面(你的原有代码) $this->webDriver->get('http://www.test.com/login'); // 输入用户名 $username = $this->webDriver->findElement(WebDriverBy::id('name')); $username->clear(); $username->sendKeys('admin'); // 输入密码(补全你的代码片段) $password = $this->webDriver->findElement(WebDriverBy::id('password')); $password->clear(); $password->sendKeys('test123'); // 触发登录操作(假设登录按钮ID为login-submit) $loginBtn = $this->webDriver->findElement(WebDriverBy::id('login-submit')); $loginBtn->click(); // 显式等待,直到捕获到AJAX响应(最多等待10秒) $this->webDriver->wait(10)->until(function () { return !empty($this->ajaxResponses); }); // 提取第一个匹配的AJAX响应 $loginResponse = reset($this->ajaxResponses); // 断言状态码为200 $this->assertEquals(200, $loginResponse['status_code'], '登录AJAX请求未返回成功状态码'); // 解析响应体(假设是JSON格式)并验证内容 $responseData = json_decode($loginResponse['response_body'], true); $this->assertArrayHasKey('success', $responseData, '响应体缺少success字段'); $this->assertTrue($responseData['success'], '登录AJAX请求返回失败'); } protected function tearDown(): void { // 关闭网络监控并退出浏览器 $this->webDriver->executeCdpCommand('Network.disable', []); $this->webDriver->quit(); } }
关键细节说明
- CDP命令调用:通过
executeCdpCommand方法调用CDP的API,Network.enable开启网络监听,Network.responseReceived监听每个响应的到达事件,Network.getResponseBody用于获取响应体的内容。 - 请求筛选:通过
strpos匹配URL来筛选目标AJAX请求,你可以根据实际需求调整筛选条件(比如请求方法、请求头)。 - 显式等待:触发登录操作后,必须等待AJAX请求完成并被捕获,否则断言会因为数据未准备好而失败。
- 版本兼容:如果使用较新的ChromeDriver,需要在
chromeOptions中添加--remote-allow-origins=*参数解决跨域限制问题。
注意事项
- 确保ChromeDriver与Chrome浏览器版本匹配,CDP的API可能会随版本更新略有变化。
- 如果使用Selenium Grid,需要确保Grid节点上的Chrome浏览器支持CDP(大部分现代版本都支持)。
- 对于HTTPS请求,若测试环境使用自签名证书,可能需要添加
--ignore-certificate-errors到Chrome启动参数中。
内容的提问来源于stack exchange,提问作者hhniao
相关产品推荐
相关产品推荐

