【问题标题】:Getting TypeError: Cannot stub non-existent own property when stubbing async method获取 TypeError:存根异步方法时无法存根不存在的自己的属性
【发布时间】:2018-12-12 01:21:19
【问题描述】:

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

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

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

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

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

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

未来

 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\regenerator-runtime\runtime.js:65:40) 在 Generator.invoke [as _invoke] (node_modules\regenerator-runtime\runtime.js:303:22) 在 Generator.prototype.(anonymous function) [as next] (node_modules\regenerator-runtime\runtime.js:117:21) 在步骤 (unit-tests\business-functions\account-assignment.tests.js:21:191) 在 C:\Projects\Platform\PlatformTesting\UITests-NotProtractor\unit-tests\business-functions\account-assignment.tests.js:21:437 在新的承诺 () 在上下文。 (unit-tests\business-functions\account-assignment.tests.js:21:99)

【问题讨论】:

    标签: async-await mocha.js sinon chai testcafe


    【解决方案1】:

    与此无关,但仅供参考 - 使用 prototype 关键字来存根实例方法 即sandbox.stub(deviceRegistryRepository.prototype, "getByName").resolve(); 并且对于静态方法不需要使用 prototype 关键字 即sandbox.stub(myStaticClass.prototype, "getMyStaticMethod").resolve();

    【讨论】:

    • 谢谢,这正是我所缺少的!
    【解决方案2】:

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

    更具体地说:您声明了一个本地变量let entityTabs;,然后分配了该变量entityTabs = sinon.stub();。最后,您尝试在该对象上存根方法 startAccountAssignment(),但它没有这样的属性,因为它不是实际的 entityTabs 模块/对象,并且基于您包含的代码 sn-ps,它不是您正在测试的模块甚至会使用的那个。

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

    【讨论】:

    • entityTabs 是它自己的模块中的一个类,因此在这个函数所在的类中被导入。import EntityNavigation from '../business-functions/entity-navigation'; const entityTabs = new EntityNavigation();
    猜你喜欢
    • 1970-01-01
    • 2019-01-18
    • 1970-01-01
    • 1970-01-01
    • 2013-08-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多