如何在 mocha 中模拟全局变量?

Posted

技术标签:

【中文标题】如何在 mocha 中模拟全局变量?【英文标题】:how to mock a global variable in mocha? 【发布时间】:2020-10-09 10:42:41 【问题描述】:

我有一个包含以下代码的文件:

在文件.ts 中:

let gateways = new Map<string, Set<number>>();

export const handler = async (event: any = ): Promise<any> => 
  let gws: Set<number> | undefined = gateways.get(action);
  console.log(gws)
  return gws

网关变量被实例化并从不同的机制设置一个值。

我正在为处理函数编写单元测试,需要模拟 gateways 变量,以便在调用 gateways.get() 时返回模拟值。 有什么办法可以做到这一点??我尝试使用rewire 模块,但它不起作用。

单元测试用例:

import * as mocha from 'mocha'
import Substitute, Arg from '@fluffy-spoon/substitute'
import handler from './helpers'
import rewire from 'rewire'
const helper = rewire('./helpers')
helper.__set__('gateways', [1, 2, 3, 4, 5, 6, 7, 8])

describe('test', () => 
  before(() => 
  )
  it('testing handler', () => 
      const result = handler('')
  )
)

【问题讨论】:

【参考方案1】:

在您的单元测试中,您可以简单地手动覆盖 getAction 或使用 Sinon 创建一个存根。以下是您手动操作的方法:

describe('EventHandler', () => 
  it('handler should correctly return values', async () => 
    const eventHandler = new EventHandler();

    // mock behaviour of `getAction`
    eventHandler.getAction = () => [1, 2, 3, 4, 5, 6, 7, 8];

    const result = await eventHandler.handler('');
    expect(result).to.eql([1, 2, 3, 4, 5, 6, 7, 8]);
  );
);

【讨论】:

【参考方案2】:

由于gateway 变量实际上不是global(它只是file.ts-模块中的“全局”),你不能直接从外部模拟它(我没有使用rewire,也许它会允许它)。但是有一种更简单的方法可以做到这一点,而不必依赖额外的库:

如何将您的handler 函数包装在一个类中并定义一个方法来封装对Map 的访问?在您的单元测试中,您可以简单地覆盖/模拟此方法的行为。比如:

export class EventHandler 
  private gateways = new Map<string, Set<number>>();

  async handler (event: any = ): Promise<any> 
       // obtain action
       const action = await ...;
       const gws: Set<number> | undefined = this.getAction(action);
       console.log(gws)
       return gws;
  

  getAction(action) 
    return this.gateways.get(action);
  



然后在您的单元测试中,您可以简单地手动覆盖 getAction 或使用 Sinon 创建存根。以下是您手动操作的方法:

describe('EventHandler', () => 
  it('handler should correctly return values', async () => 
    const eventHandler = new EventHandler();

    // mock behaviour of `getAction`
    eventHandler.getAction = () => [1, 2, 3, 4, 5, 6, 7, 8];

    const result = await eventHandler.handler('');
    expect(result).to.eql([1, 2, 3, 4, 5, 6, 7, 8]);
  );
);

【讨论】:

我喜欢这个解决方案,但处理程序方法是一个 lambda 函数,因此无法将其转换为类。我只需要在一个函数中完成它 有一点错别字 - 我现在已经从方法定义中删除了 =&gt;。现在应该可以工作了:) 如果不能,请添加您当前如何调用handler-function? 不想转换成类。这是一个 Lambda 函数 :) 好吧,恐怕我不知道该怎么做,也许其他人知道解决问题的方法:)

以上是关于如何在 mocha 中模拟全局变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Mockito 中模拟全局变量

如何在 JEST 测试中模拟全局 Vue.js 变量

如何在运行时确定共享库中全局变量的地址范围?

Spectron,mocha和chai可以声称变量在Electron-app中具有预期值吗?

在 Jest 中模拟全局变量

安装多个 typescript 类型定义,声明相同的全局变量