
本文旨在解决 cypress page object model (pom) 中常见的 `typeerror: [method] is not a function` 错误。此错误通常发生在尝试直接在类定义上调用方法,而非在其实例化对象上调用时。文章将详细解释此错误的原因,并提供正确的类实例化和方法调用方式,确保在 cypress 测试中 page object 能够正常工作。
引言:理解 TypeError: is not a function
在 JavaScript 开发中,TypeError: [object].method is not a function 是一个非常常见的错误。它表明你试图调用的 method 并不是 [object] 的一个可执行函数。在 Cypress 的 Page Object Model (POM) 实践中,这个错误通常意味着你正在尝试在一个类的定义上调用其方法,而不是在一个已经创建的该类的实例(对象)上调用。
当你在 Cypress 测试文件中导入一个 Page Object 类并尝试直接调用其方法时,例如 homePage.populateDataBasedOnJsonValues(data),如果 homePage 仅仅是导入的类定义本身,而非该类的一个实例,就会触发此 TypeError。
JavaScript 类与实例:核心概念
理解 JavaScript 中的类(Class)和实例(Instance)是解决此类问题的关键。
类 (Class):类是创建对象的蓝图或模板。它定义了对象将拥有的属性(数据)和方法(行为)。例如,HomePage 类定义了一个网页的结构和与之交互的方式。实例 (Instance):实例是根据类这个蓝图创建出来的具体对象。每个实例都拥有类定义的属性和方法,并且可以有自己独立的状态。只有通过类的实例,我们才能调用类中定义的方法。
简而言之,你不能直接在蓝图上“操作”;你必须先根据蓝图“建造”一个东西(即创建一个实例),然后才能对这个东西进行操作。
问题剖析:错误的类方法调用
考虑以下 Cypress 测试文件 homePageTest.cy.js 的初始代码:
// homePageTest.cy.jsimport HomePage from '../Hompage.js'; // 假设这里导入的是类定义it("some test", () => { cy.fixture("jsonValues").then((data) => { // 错误:直接在导入的类定义上调用方法 // HomePage 此时是一个类,而不是类的实例 HomePage.populateDataBasedOnJsonValues(data); });});
以及对应的 Page Object 类 homepage.js:
// homepage.jsclass HomePage { _getcheckBox(question) { // 这里的 this.get 假设是 cy.get 的误写,或期望有一个内部的 get 方法 // 正确的 Cypress 做法应直接使用 cy.get return cy.get(`div[class$='checkbox-component-${question}'] > label > input`); } populateDataBasedOnJsonValues(answers) { for (let key in answers) { // 错误:在类内部调用其他方法时,必须使用 'this' 关键字 // const question = _getcheckBox(answers[key]); // 这会导致 ReferenceError 或其他问题 const questionElement = this._getcheckBox(answers[key]); // 正确 questionElement.click(); } }}export default HomePage;
在 homePageTest.cy.js 中,import HomePage from ‘../Hompage.js’ 语句导入的是 HomePage 类本身,而不是 HomePage 类的一个具体对象。因此,当你尝试执行 HomePage.populateDataBasedOnJsonValues(data) 时,JavaScript 引擎会发现 populateDataBasedOnJsonValues 不是 HomePage 类定义上的静态方法(它是一个实例方法),从而抛出 TypeError: HomePage.populateDataBasedOnJsonValues is not a function。
解决方案:正确实例化 Page Object
要解决这个问题,你需要在调用 HomePage 类的方法之前,先创建它的一个实例。这通过 new 关键字来实现。
修改 homePageTest.cy.js 如下:
// homePageTest.cy.jsimport HomePage from '../Hompage.js';// 在测试套件或测试用例开始时,创建 HomePage 类的一个实例const homePage = new HomePage(); // 关键:实例化 HomePage 类it("some test", () => { cy.fixture("jsonValues").then((data) => { // 现在 homePage 是 HomePage 类的一个实例,可以正常调用其方法 homePage.populateDataBasedOnJsonValues(data); });});
通过 const homePage = new HomePage();,我们创建了一个名为 homePage 的对象,它是 HomePage 类的一个具体实例。现在,homePage 拥有 HomePage 类中定义的所有实例方法,因此 homePage.populateDataBasedOnJsonValues(data) 可以被正确调用。
Page Object 内部方法调用规范
除了外部测试文件中的实例化问题,Page Object 内部的方法调用也需要遵循规范。在 HomePage 类内部,当一个实例方法需要调用同一个实例的另一个方法时,必须使用 this 关键字来引用当前实例。
修改 homepage.js 如下:
// homepage.jsclass HomePage { // 确保 _getcheckBox 返回 Cypress 命令链 _getcheckBox(question) { return cy.get(`div[class$='checkbox-component-${question}'] > label > input`); } populateDataBasedOnJsonValues(answers) { for (let key in answers) { // 正确:使用 'this' 关键字调用当前实例的 _getcheckBox 方法 const questionElement = this._getcheckBox(answers[key]); questionElement.click(); } }}export default HomePage;
在 populateDataBasedOnJsonValues 方法中,this._getcheckBox(answers[key]) 确保你调用的是当前 HomePage 实例的 _getcheckBox 方法。如果省略 this,JavaScript 会尝试在当前作用域查找一个名为 _getcheckBox 的函数,这通常会导致 ReferenceError。
完整示例代码
为了清晰地展示正确的实践,以下是修正后的完整代码示例:
homepage.js (Page Object)
// cypress/page-objects/homepage.jsclass HomePage { // 私有辅助方法,用于获取复选框元素 _getcheckBox(question) { // 使用模板字符串构建选择器,并返回 Cypress 命令链 return cy.get(`div[class$='checkbox-component-${question}'] > label > input`); } // 根据 JSON 数据填充页面上的复选框 populateDataBasedOnJsonValues(answers) { for (let key in answers) { // 确保使用 'this' 关键字调用当前实例的内部方法 const questionElement = this._getcheckBox(answers[key]); questionElement.click(); } }}export default HomePage;
homePageTest.cy.js (Cypress 测试文件)
// cypress/e2e/homePageTest.cy.jsimport HomePage from '../page-objects/homepage.js'; // 确保路径正确// 在测试文件顶部或 beforeEach 钩子中实例化 Page Objectconst homePage = new HomePage(); // 实例化 HomePage 类describe('Homepage Checkbox Tests', () => { beforeEach(() => { // 可选:在每个测试前访问页面 cy.visit('/'); }); it("should populate checkboxes based on json values", () => { cy.fixture("jsonValues").then((data) => { // 调用实例方法,传入从 fixture 加载的数据 homePage.populateDataBasedOnJsonValues(data); }); // 添加断言以验证操作是否成功 // 例如: // cy.get('input[type="checkbox"]:checked').should('have.length', Object.keys(data).length); });});
jsonValues.json (Fixture 文件示例)
// cypress/fixtures/jsonValues.json{ "question1": "optionA", "question2": "optionB", "question3": "optionC"}
总结与最佳实践
实例化是关键:在 JavaScript 中,当你定义一个类并希望使用其非静态方法时,必须首先使用 new 关键字创建该类的一个实例。TypeError: is not a function 最常见的原因就是忘记了这一步。this 关键字的正确使用:在类的实例方法内部,如果需要调用同一个实例的其他方法或访问实例属性,请务必使用 this. 前缀。Cypress POM 的优势:Page Object Model 旨在提高测试代码的可读性、可维护性和复用性。通过将页面元素和交互逻辑封装在独立的类中,可以使测试脚本更简洁,并且当 UI 发生变化时,只需修改 Page Object 文件,而无需修改所有相关的测试用例。清晰的导入路径:确保 import 语句中的路径是正确的,指向你的 Page Object 文件。
遵循这些原则,你将能够有效地在 Cypress 项目中构建和使用 Page Object Model,避免常见的 TypeError,并编写出健壮、易于维护的自动化测试。
以上就是Cypress POM 实践:正确实例化类以避免 TypeError的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1533157.html
微信扫一扫
支付宝扫一扫