获取类型错误:在存根异步方法时无法存根不存在的自有属性

问题描述 投票:0回答:2

我正在尝试为我们的小型但很快就会增长的 testcafe 业务功能库编写单元测试 - 即那些使用页面文件的库,来测试任何不简单的逻辑。

为此,我正在尝试为此函数编写我的第一个单元测试 entityTabs - 这是一个导入的异步模块,ui 是一个导入的非异步模块,accountAssignmentControls 是一个页面文件。这里提到的那些功能。在模块中进一步定义。 t 是 testcafe 导入。

最初,我想删除所有函数并测试 statAccountAssignments 是否被调用一次(之后我将测试传入数据的各种组合,但我无法超越第一个障碍)。

我单位测试了我们的非异步无头测试库,但是

  • a) 这是非异步的并且
  • b) 这是较旧的节点,因此某些结构等有所不同。

其中一位开发人员使用 chair、mocha 和 sinon 添加了一些单元测试 - 但这些是针对项目的非异步部分(主要是文件处理),所以我无法应用他所写的内容。

FUT

     async assignAccounts(assignments) {
        await entityTabs.startAccountAssignment();
        ui.logWithTimeStamp('WAiting for Account assignment dialog to appear', 2);
            await t
              .expect(accountAssignmentControls.accountAssignmentHeader.innerText)
              .contains('Account Assignment', 'Header contains Account Assignment');
            ui.logWithTimeStamp('Header visible waiting for accounts list', 2);
            await this.checkAccountList();
        
            const assignmentsCount = assignments.length;
            ui.logWithTimeStamp('Doing ' + assignmentsCount + ' assignments: ', 1);
            for (let i=0; i<assignmentsCount; i++) {
              ui.logWithTimeStamp(i + ': ' + JSON.stringify(assignments[i]), 1);
              if (assignments[i].type === 'credit') {
                await this.assignCreditAccount(assignments[i]);
              } else if (assignments[i].type === 'debit') {
                await this.assignDebitAccount(assignments[i]);
              } else {
                await this.assignFullAccount(assignments[i]);
              }
              ui.logWithTimeStamp('Assignment done', 3);
              await t.takeScreenshot();
            };
          }

当前失败的测试

    import chai from 'chai';
    import sinon from 'sinon';
    import sinonChai from 'sinon-chai';
    
    import AccountAssignment from '../../business-functions/account-assignment';
    
    let accountAssignmentControls;
    // let busyLoader;
    let entityTabs;
    let ui;
    let t;
    // Register the sinon-chai extensions.
    chai.use(sinonChai);
    const expect = chai.expect;
    
    // We must turn off the no-invalid-this rule because of how mocha uses this to be the current test fixture.
    /* eslint no-invalid-this: "off" */
    
    describe('business-functions - Account assignment', function() {
      describe('AccountAssignment class', function() {
        describe('assignAccounts', function() {
          let sandbox;
    
          before(() => {
            sandbox = sinon.sandbox.create();
          });
    
          after(() => {
            sandbox.restore();
          });
    
          describe('when one of each assignment', function() {
            it('starts assignment', async function() {
              const fakeResponse = 'dont care';
    
              const accountAssignment = new AccountAssignment();
              t = sinon.stub();
              entityTabs = sinon.stub();
              ui = sinon.stub();
              ui.logWithTimeStamp = sinon.stub();
              accountAssignmentControls = sinon.stub();
            //  let f = sinon.fake();
              let startAccountAssignment = sandbox
                .stub(entityTabs, 'startAccountAssignment')
                .resolves(fakeResponse);
             // sandbox.stub(t, 'expect');
              sandbox
                .stub(accountAssignment, 'checkAccountList')
                .resolves(fakeResponse);
              sandbox
                .stub(accountAssignment, 'assignCreditAccount')
                .resolves(fakeResponse);
              sandbox
                .stub(accountAssignment, 'assignDebitAccount')
                .resolves(fakeResponse);
              sandbox
                .stub(accountAssignment, 'assignFullAccount')
                .resolves(fakeResponse);
              sandbox
                .stub(accountAssignmentControls, 'accountAssignmentHeader')
                .resolves(fakeResponse);
    
              sandbox
                .stub(t, 'expect')
                .resolves(fakeResponse);
              sandbox
                .stub(t, 'contains')
                  .resolves(fakeResponse);
              sandbox
                .stub(t, 'takeScreenshot')
                  .resolves(fakeResponse);
    
              await accountAssignment.assignAccounts({});
              expect(startAccountAssignment).to.be.callledOnce;
            });
          });
        });
      });
    });

运行时得到

TypeError:无法存根不存在的自有属性 startAccountAssignment 在 Sandbox.stub (node_modules\sinon\lib\sinon\sandbox.js:286:19) 在 Context._callee$ (C:/Projects/Platform/PlatformTesting/UITests-NotProtractor/unit-tests/business-functions/account-assignment.tests.js:49:14) 在 tryCatch (node_modules 生成器运行时 untime.js:65:40) 在 Generator.invoke [as _invoke] (node_modules 生成器运行时 untime.js:303:22) 在 Generator.prototype.(匿名函数) [作为下一个] (node_modules 生成器运行时 untime.js:117:21) 在步骤(单元测试实用功能ccount-assignment.tests.js:21:191) 在 C:\Projects\Platform\PlatformTesting\UITests-NotProtractor\unit-tests usiness-functions ccount-assignment.tests.js:21:437 在新的承诺 () 在上下文中。 (单元测试实用功能ccount-assignment.tests.js:21:99)

async-await mocha.js sinon chai testcafe
2个回答
13
投票

使用 prototype 关键字来删除实例方法,即

sandbox.stub(deviceRegistryRepository.prototype, "getByName").resolve();

对于静态方法,不需要使用 prototype 关键字,即

sandbox.stub(myStaticClass.prototype, "getMyStaticMethod").resolve();


4
投票

您没有正确存根

entityTabs
,并且您正在测试的模块没有使用您的存根。

更具体地说:您已经声明了一个本地变量

let entityTabs;
,然后分配了该变量
entityTabs = sinon.stub();
。最后,您尝试在该对象上删除一个方法
startAccountAssignment()
,但它没有这样的属性,因为它不是实际的
entityTabs
模块/对象,并且根据您包含的代码片段,它不是您正在测试的模块甚至会使用它。

根据

entityTabs
对象的编写方式(它是在它自己的模块中吗?是单例吗?它是一个类吗?),您需要导入它,并存根您想要模拟的方法,或者您想要使用类似
proxyquire
的东西来模拟
entityTabs

© www.soinside.com 2019 - 2024. All rights reserved.