You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cypress页面对象模型(POM)中递归方法引用错误问题求助

解决Cypress类中递归方法的引用错误问题

这个问题我之前也碰到过,核心原因是类方法里的递归调用没有正确绑定当前实例的上下文,而且Cypress的异步回调会改变this的指向,咱们一步步来修复:

问题根源

你在类内部直接调用choose_randCategory(),但这个方法是类的成员,不是全局函数,必须通过类实例的this来访问。但Cypress的.then()回调是异步执行的,回调内部的this默认指向全局对象(浏览器中是window),不是你的DropDown_PO实例,所以会抛出ReferenceError。

解决方案:绑定上下文

有两种常用的方式来解决这个问题:

方法1:保存实例引用到变量

在方法开头把当前实例的this保存到一个变量(比如self),然后在回调里用这个变量调用递归方法:

class DropDown_PO {
  choose_randCategory(id = String(Math.floor(Math.random() * (15)) + 1), number = 2) {
    // 保存当前类实例的引用,避免回调中this指向变化
    const self = this;
    let reccur = number + 1;
    
    if (id != 0) {
      cy.get("#category_selector_5>:nth-child(" + id + ")").then(($elem) => {
        cy.get("#category_selector_5").select($elem.text(), { force: true });
      });
    }

    cy.get("div[class='category_level_" + String(number) + "']").find('select').find('option').its('length').then(($firstele) => {
      let randomlist = Math.floor(Math.random() * ($firstele - 2)) + 2;
      cy.get("div[class='category_level_" + String(number) + "']").find('select').find('option').eq(randomlist).then(($choice) => {
        cy.get("div[class='category_level_" + String(number) + "']").find('select').select($choice.text(), { force: true });
        cy.wait(4000);
      });
    });

    cy.get("body").then(($body) => {
      if ($body.find("div[class='category_level_" + String(number + 1) + "']").length) {
        // 使用保存的self调用递归方法
        self.choose_randCategory(0, reccur);
      }
    });
  }
}

方法2:使用箭头函数保留上下文

箭头函数不会绑定自己的this,而是继承外层作用域的this,所以把Cypress的回调改成箭头函数,就能直接用this调用类方法:

class DropDown_PO {
  choose_randCategory(id = String(Math.floor(Math.random() * (15)) + 1), number = 2) {
    let reccur = number + 1;
    
    if (id != 0) {
      cy.get("#category_selector_5>:nth-child(" + id + ")").then(($elem) => {
        cy.get("#category_selector_5").select($elem.text(), { force: true });
      });
    }

    cy.get("div[class='category_level_" + String(number) + "']").find('select').find('option').its('length').then(($firstele) => {
      let randomlist = Math.floor(Math.random() * ($firstele - 2)) + 2;
      cy.get("div[class='category_level_" + String(number) + "']").find('select').find('option').eq(randomlist).then(($choice) => {
        cy.get("div[class='category_level_" + String(number) + "']").find('select').select($choice.text(), { force: true });
        cy.wait(4000);
      });
    });

    // 把回调改成箭头函数,this会指向类实例
    cy.get("body").then(($body) => {
      if ($body.find("div[class='category_level_" + String(number + 1) + "']").length) {
        this.choose_randCategory(0, reccur);
      }
    });
  }
}

额外优化建议

  1. 替换硬编码等待:cy.wait(4000)是不可靠的,最好用cy.intercept()监听动态加载分类的Ajax请求,等请求完成后再继续:

    // 在测试用例开头拦截请求
    cy.intercept('GET', '/api/categories/**').as('loadCategories');
    
    // 选择选项后等待请求完成
    cy.get(`div.category_level_${number}`).find('select').select($choice.text(), { force: true });
    cy.wait('@loadCategories');
    
  2. 使用模板字符串简化选择器:把字符串拼接改成模板字符串,代码更易读:

    cy.get(`div.category_level_${number}`).find('select')
    

内容的提问来源于stack exchange,提问作者cy.user

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 21:52:29