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

Cypress V10 BDD测试报错:无法读取undefined的'mobileHandset'属性

解决Cypress Cucumber BDD模式下this.data未定义的问题

问题描述

将Cypress Mocha框架转换为BDD模式后,测试运行报错:TypeError: Cannot read properties of undefined (reading 'mobileHandset')。已将BeforeEach文件移至Support目录,问题仍未解决。

相关代码

Feature文件

Feature: End to End Shopping Purchase Validation

 Registered user will be able to purchase an item and have it shipped to their country

    Scenario: Customer Purchase and delivery
    
    Given  I am on the eCommerce page
    When I add items to cart 
    And I confirm shopping cart total
    Then I select my delivery country and see a thank for your order notification

步骤定义

import { Given, And, Then, When } from "@badeball/cypress-cucumber-preprocessor";
import Homepage from '../../../support/pageObjects/Homepage'
import orderSummaryPage from '../../../support/pageObjects/orderSummaryPage'
import completeOrderPage from '../../../support/pageObjects/completeOrderPage'
const data = require ('../../../fixtures/example.json');

const homepage = new Homepage()
const StartCheckout = new orderSummaryPage()
const CompleteOrder = new completeOrderPage()

Given(/^I am on the eCommerce page$/, () => {
    cy.visit(``+"/angularpractice/")
});

When(/^I add items to cart$/, function() {
  homepage.getShopTab().click({force:true}) 
  this.data.mobileHandset.forEach(function(element) {
    cy.AddToCart(element)  
  }); 
  StartCheckout.getBasketCheckoutButton().click()
});

When(/^I confirm shopping cart total$/, () => {
    let sum=0
    CompleteOrder.getProductCost().each(($e1, index, $list) =>{
      const unitCost=$e1.text()  
      let res= unitCost.split(" ") 
      res= res[1].trim() 
      sum=Number(sum)+Number(res)
  }).then(function() 
  {
      cy.log(sum)
  })
});

Then(/^I select my delivery country and see a thank for your order notification$/, () => {
    StartCheckout.getStartCheckoutButton().click()
    CompleteOrder.getShippingCountry().type('United Kingdom')
    CompleteOrder.getShippingCountryConfirm().click()
    CompleteOrder.getTermsConditionsCheckbox().click({force: true})
    CompleteOrder.getPurchaseButton().click()
    
    CompleteOrder.getPurchaseAlert().then(function(element){
       const actualText= element.text()
      expect(actualText.includes('Success')).to.be.true
     }) 
});

测试数据(example.json)

{
  "name": "MY_NAME",
  "gender": "Female",
  "mobileHandset": ["Blackberry", "Nokia Edge"]
}

BeforeEach代码(Support目录下)

beforeEach(function()
{
    cy.fixture('example').then(function(data){ 
        this.data=data 
       })
})

问题原因

@badeball/cypress-cucumber-preprocessor 默认不将步骤定义中的this绑定到Cypress的运行上下文,导致this.data无法访问到BeforeEach中挂载的fixture数据。

解决方案

方案1:使用Cypress全局环境存储数据

修改BeforeEach代码,将数据存入Cypress全局环境:

beforeEach(function() {
  cy.fixture('example').then(function(data) {
    Cypress.env('testData', data);
  });
});

修改步骤定义中的调用逻辑:

When(/^I add items to cart$/, function() {
  homepage.getShopTab().click({force:true}); 
  const testData = Cypress.env('testData');
  testData.mobileHandset.forEach(function(element) {
    cy.AddToCart(element);  
  }); 
  StartCheckout.getBasketCheckoutButton().click();
});

方案2:开启预处理器的bindToRunInstance配置

在cypress.config.js中添加配置,让步骤定义的this指向Cypress运行实例:

const { defineConfig } = require("cypress");
const createBundler = require("@bahmutov/cypress-esbuild-preprocessor");
const addCucumberPreprocessorPlugin = require("@badeball/cypress-cucumber-preprocessor").addCucumberPreprocessorPlugin;
const createEsbuildPlugin = require("@badeball/cypress-cucumber-preprocessor/esbuild").createEsbuildPlugin;

module.exports = defineConfig({
  e2e: {
    async setupNodeEvents(on, config) {
      const bundler = createBundler({
        plugins: [createEsbuildPlugin(config)],
      });

      on("file:preprocessor", bundler);
      await addCucumberPreprocessorPlugin(on, config);

      return config;
    },
    specPattern: "cypress/e2e/**/*.feature",
    experimentalSessionAndOrigin: true,
    env: {
      "cypress-cucumber-preprocessor": {
        bindToRunInstance: true
      }
    }
  },
});

确保步骤定义中使用普通函数(而非箭头函数),即可正常访问this.data。

方案3:直接使用导入的fixture数据

利用已导入的data变量替代this.data,快速解决问题:

When(/^I add items to cart$/, function() {
  homepage.getShopTab().click({force:true}); 
  data.mobileHandset.forEach(function(element) {
    cy.AddToCart(element);  
  }); 
  StartCheckout.getBasketCheckoutButton().click();
});

此方案适合快速验证,但动态切换fixture时灵活性不足。

内容的提问来源于stack exchange,提问作者fypnlp

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 17:25:57