【问题标题】:Mocking functions in JestJest 中的模拟函数
【发布时间】:2018-09-14 09:14:50
【问题描述】:

我是 JavaScript 测试的新手,目前正在尝试为我创建的商店(只是一个 ES6 类)编写一些测试用例。我正在使用 Jest,因为这是我们通常用于 React 项目的,尽管在这里我不是在测试 React 组件,而只是一个包装功能的类。

我正在测试的类扩展了另一个类,并在其中定义了各种方法。我想测试这些方法(无论它们是否被调用),以及类中声明的属性是否随着调用相应的类方法以及何时发生变化。

现在我已经阅读了有关模拟函数的信息,但据我了解,它们只能检查函数被调用的次数,但不能复制该功能。但就我而言,我需要方法的功能,因为我将检查这些方法在调用时更改的类成员值。

我不确定这是否是正确的方法。在 Jest 中测试函数而不进行模拟是错误的吗?并且推论,测试功能的内部运作?我们什么时候在测试时模拟函数?

我面临的问题是我正在从事的项目是一个大型项目,其中存在多个级别的类/函数依赖关系,并且很难通过 Jest 对其进行测试,因为它需要通过所有他们。当我在项目中使用别名作为文件路径时,如果 Jest 找不到任何模块,它会抛出错误。我知道可以将 Webpack 与 Jest 一起使用,但是代码中的许多依赖类/函数不在 React 中,并且它们的别名文件路径不是由 Webpack 维护的。

import { getData } from 'service/common/getData';

class Wrapper extends baseClass {
    someVariable = false;
    payload = null;

    changeVariable() {
        this.someVariable = true;
    }

    async getData() {
        super.start();
        response = await fetchData();
        this.payload = response;
        super.end();
    }
}

这是我所拥有的实际代码的一个小表示。因为我在远程机器上工作,所以不能在这里发布整个课程。基本上,我想测试changeVariable在调用时是否被调用,以及在调用时是否成功将someVariable更改为true;同样,在网络请求完成后检查payload 的值。请注意,fetchData 是在其他文件中定义的,但对于测试 getData 方法至关重要。此外,此处用于导入 getData 的路径 (service/common/getData) 不是绝对路径,而是 Webpack 中未定义的别名,而是其他地方。因此,Jest 无法解析 getData。如果我模拟getData,我将不必担心这一点,但我相信我将无法测试它的功能。

【问题讨论】:

  • 贴一些代码。
  • @RuChernChong:已添加代码。

标签: javascript unit-testing jestjs


【解决方案1】:

@maverick 使用 jest 测试你的类方法是完全可以的。检查链接中的代码示例 -

https://repl.it/repls/ClumsyCumbersomeAdware

index.js

class Wrapper {
  constructor(){
    this.someVariable = false;
  }
  changeVariable(){
    this.someVariable = true;
  }

  getData(){
    return new Promise(resolve => resolve('some data'));
  }
}


module.exports = Wrapper;

index.test.js

const Wrapper = require('./index');

const wrapper = new Wrapper();

describe('Wrapper tests', () => {
  it('should changeVariable', () => {
    wrapper.changeVariable();
    expect(wrapper.someVariable).toBe(true);
  });

  it('should get some data', () => {
    wrapper.getData().then( res => expect(res).toBe('some data'));
  });
});

这是一个非常简单的示例,在现实生活中,异步调用要复杂得多,并且依赖于 3rd 方库或其他项目模块。在这种情况下,将所有依赖项注入到类中然后单独模拟是有意义的。例如 -

class GMapService {
  constructor(placesApi, directionApi){
      this.placesApi = placesApi;
      this.directionApi = directionApi;
  }

  getPlaceDetails(){
    this.placesApi.getDetails('NYC');
  }

  getDirections(){
    this.directionApi.getDirections('A', 'B');
  }
}

现在您可以轻松地模拟 placesApi 和 directionApi,并单独测试它们,而无需实际需要 Google Map 依赖项。

希望这会有所帮助! ?

【讨论】:

    猜你喜欢
    • 2022-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-18
    • 2021-01-22
    相关资源
    最近更新 更多