【问题标题】:how to mock a global variable in mocha?如何在 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('')
  })
})

【问题讨论】:

    标签: node.js typescript unit-testing mocking mocha.js


    【解决方案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 函数 :)
      • 好吧,恐怕我不知道该怎么做,也许其他人知道解决问题的方法:)
      猜你喜欢
      • 2015-04-04
      • 2016-04-26
      • 2018-11-12
      • 2016-11-15
      • 2017-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多