在Jest中模拟函数

时间:2018-04-04 17:43:37

标签: javascript unit-testing jestjs

我是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方法至关重要。此处使用的路径(service/common/getData)用于导入getData不是绝对路径,而是在Webpack中定义的别名,但在其他地方。由于这个原因,Jest无法解决getData。如果我嘲笑getData,我将不必担心这个问题,但是我无法测试它的功能。

1 个答案:

答案 0 :(得分:0)

@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'));
  });
});

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

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依赖项。

希望这有帮助!