首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当被类扩展时,Mocha发现全局变量是未定义的。

当被类扩展时,Mocha发现全局变量是未定义的。
EN

Stack Overflow用户
提问于 2022-02-05 11:52:24
回答 1查看 237关注 0票数 1

我有以下的ES6模块从一个Chromecast接收器,我想测试使用摩卡.

代码语言:javascript
复制
// SUT - app.js
import { Queue } from 'queue.js'
export const app = async () => {
  const context = cast.framework.CastReceiverContext.getInstance();
  const options = {};
  options.queue = new Queue();
  context.start(options);
}

此代码运行在Chromecast用户代理中,该代理提供对全局cast对象的访问。此cast对象公开一个api,从而使JS线程能够直接与Chromecast CAF交互。此强制转换变量在运行时总是可用的。

队列类有点不寻常,因为为了让它根据CAF框架文档工作,必须从框架cast.framework.QueueBase扩展一个抽象类.

代码语言:javascript
复制
// queue.js
class Queue extends cast.framework.QueueBase {
  initialize(){
    // build queue here
  }
}

现在,我想编写一些单元测试来检查我的app函数是否正确。例如:

代码语言:javascript
复制
// app.test.js
import { app } from 'app.js';
it('should do some stuff', async function () {
  // inject a mock cast object
  global.cast = {
    framework: {
      QueueBase: class {},
      CastReceiverContext: {
        getInstance: () => {},
      },
    },
  };
  await app();
  // Make some assertions
});

然而,即使我使用global.cast注入一个模拟,对于所有对cast对象的常规引用都足够了,但在类正在扩展注入的cast对象的情况下,显然它还不可用,并且我收到以下错误:

ReferenceError: cast未定义

我发现了一个丑陋的黑客让这个错误消失了。如果我将下面的片段放在类声明的前面,那么我可以在运行时注入模拟,它不仅适用于Mocha,而且也适用于Chromecast设备上的执行.

代码语言:javascript
复制
try {
  // The following line throws in Mocha's node environment
  // but executes fine on the Chromecast device
  if (cast) {
  }
} catch {
  global.cast = {
    framework: {
      QueueBase: class {},
    },
  };
}

export class Queue extends cast.framework.QueueBase {
...

但是,我想找到一个更好的解决方案,这样我就不必用这个黑客来污染我的生产代码了,这只允许我运行测试。

我的.mocharc.yml文件如下所示:

代码语言:javascript
复制
require:
  - '@babel/register'
  - 'ignore-styles'
  - 'jsdom-global/register'
  - 'babel-polyfill'

..。我执行测试的命令是:

摩卡--递归--使用严格

最后,我的.babelrc文件如下所示:

代码语言:javascript
复制
{
    "presets": [
        [
            "@babel/preset-env"
        ]
    ],
    "plugins": [
        "inline-svg",
        "import-graphql"
    ]
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-05 15:45:09

静态导入总是首先评估的,因此操作顺序大致如下:

代码语言:javascript
复制
import { Queue } from 'queue.js'
代码语言:javascript
复制
class Queue extends cast.framework.QueueBase { // ReferenceError outside Chromecast!
  initialize(){
    // build queue here
  }
}
代码语言:javascript
复制
global.cast = {
    framework: {
      QueueBase: class {},
      CastReceiverContext: {
        getInstance: () => {},
      },
    },
  };

您可以看到,模拟是在app.js中对app.js的引用之后创建的。

在导入应用程序模块之前运行模拟创建的唯一可靠方法是使用动态导入:

代码语言:javascript
复制
// app.test.js
it('should do some stuff', async function () {
  // inject a mock cast object
  global.cast = {
    framework: {
      QueueBase: class {},
      CastReceiverContext: {
        getInstance: () => {},
      },
    },
  };
  const { app } = await import('app.js');
  await app();
  // Make some assertions
  delete global.cast;
});

如果不希望在每个测试中重复模拟创建和import,则可以将这两项移出测试定义:

代码语言:javascript
复制
// app.test.js
// inject a mock cast object
global.cast = {
  framework: {
    QueueBase: class {},
    CastReceiverContext: {
      getInstance: () => {},
    },
  },
};
const { app } = await import('app.js');
it('should do some stuff', async function () {
  await app();
  // Make some assertions
});
// Optionally clean up the mock after all tests
after(() => delete global.cast);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70997750

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档