Cypress - 处理 XHR 请求
Cypress - 处理网络请求 (XHR/Fetch)
Section titled “Cypress - 处理网络请求 (XHR/Fetch)”现代 Web 应用大量依赖网络请求(如 XHR - XMLHttpRequest,或 Fetch API 调用)来与服务器通信,无需整页刷新即可获取数据或提交信息。这些请求对于动态内容和用户交互至关重要。
Cypress 提供了强大的工具来管理和测试这些网络请求。你可以侦测(spy)请求、断言其属性,甚至模拟(stub)或伪造(mock)响应。这允许你通过控制外部依赖来创建更快、更可靠的测试。你可以在浏览器的开发者工具(通常在 ‘Network’ 选项卡下)中观察原始的网络活动。
在浏览器开发者工具中检查网络请求时,你通常会看到诸如请求 URL、方法(GET、POST 等)、状态码(例如 200 OK、404 Not Found)、请求/响应头(如 Content-Type、Authorization)以及响应体(例如 JSON 数据)等详细信息。
Cypress 提供了两个主要的网络交互命令:cy.intercept() 用于管理测试期间由你的应用发起的网络请求;cy.request() 用于直接从测试代码中发起 HTTP 请求(例如,用于 API 测试或测试设置)。
使用 cy.intercept() 管理应用网络请求
Section titled “使用 cy.intercept() 管理应用网络请求”cy.intercept() 是现代、多功能的命令,用于拦截和管理你的应用发起的 HTTP 请求和响应。你可以用它来:
- 等待特定请求完成后再继续。
- 断言请求和响应数据(请求头、请求体、状态码)。
- 模拟(Stub)响应以测试各种场景(例如,空数据、错误状态),而无需真实后端。
侦测请求并断言
Section titled “侦测请求并断言”你可以拦截请求,为其创建别名,等待其完成,然后进行断言:
describe('Network Interception Test', () => { it('should fetch user data and verify response', () => { // Intercept GET requests to '/api/users' // 拦截对 '/api/users' 的 GET 请求 cy.intercept('GET', '/api/users').as('getUsers');
cy.visit('/dashboard'); // Action that triggers the API call // 触发 API 调用的动作
// Wait for the aliased request and assert its response // 等待别名请求并断言其响应 cy.wait('@getUsers').then((interception) => { expect(interception.response.statusCode).to.eq(200); expect(interception.response.body).to.be.an('array').and.not.be.empty; // Further assertions on response body or headers // 对响应体或请求头进行进一步断言 }); });});模拟响应 (Stubbing Responses)
Section titled “模拟响应 (Stubbing Responses)”模拟允许你为请求定义一个伪造的响应,使测试具有确定性并独立于后端状态:
describe('Network Stubbing Test', () => { it('should display message when no data is returned', () => { // Stub GET requests to '/api/items' to return an empty array // 模拟对 '/api/items' 的 GET 请求,使其返回空数组 cy.intercept('GET', '/api/items', { statusCode: 200, body: [] }).as('getItems');
cy.visit('/items-list');
cy.wait('@getItems'); cy.contains('No items found.').should('be.visible'); });
it('should load data from a fixture', () => { // Stub response using a fixture file (e.g., cypress/fixtures/products.json) // 使用 fixture 文件模拟响应(例如 cypress/fixtures/products.json) cy.intercept('GET', '/api/products', { fixture: 'products.json' }).as('getProducts');
cy.visit('/products'); cy.wait('@getProducts'); // Assert that the UI reflects data from products.json // 断言 UI 反映了 products.json 中的数据 cy.get('.product-item').should('have.length.greaterThan', 0); });});有关更全面的示例和 cy.intercept() 的高级用法(例如动态修改响应),请参阅 Cypress 官方文档中关于网络请求的部分。
使用 cy.request() 直接发起 HTTP 请求
Section titled “使用 cy.request() 直接发起 HTTP 请求”cy.request() 用于当你的测试脚本需要在应用 UI 交互之外,直接向服务器发起 HTTP 请求时。这通常用于:
- 在测试之前/之后填充数据或清理状态。
- 直接测试你的 API 端点。
- 获取测试逻辑所需的外部数据。
以下是使用 cy.request() 获取数据并断言其属性的示例:
describe('Direct API Request Test', () => { it('should fetch comments from a public API', () => { cy.request('GET', 'https://jsonplaceholder.cypress.io/comments').as('commentsReq');
cy.get('@commentsReq').should((response) => { expect(response.status).to.eq(200); expect(response.body).to.be.an('array').and.to.have.length.of.at.least(100); expect(response).to.have.property('headers'); expect(response.headers).to.have.property('content-type').and.include('application/json'); }); });});cy.request() 会自动处理 cookie,并且可以通过各种选项进行配置,包括方法、URL、请求体、请求头和认证。它是作为测试策略一部分与 API 交互的强大工具。