简体   繁体   English

开玩笑的模拟功能

[英]Mocking functions in Jest

I am new to JavaScript testing and currently trying to write some test cases for a store (just an ES6 class) I created. 我是JavaScript测试的新手,目前正在尝试为我创建的商店(只是ES6类)编写一些测试用例。 I am using Jest as this is what we usually use for React projects, although here I am not testing a React Component but just a class wrapping a functionality. 我使用的是Jest,因为这是我们通常用于React项目的内容,尽管这里我不是在测试React组件,而只是在包装一个功能类。

The class I am testing extends another class, and has various methods defined in it. 我正在测试的类扩展了另一个类,并在其中定义了各种方法。 I want to test these methods (whether they are called or not), and also whether the properties declared in the class change as and when the corresponding class methods are called. 我想测试这些方法(是否被调用),以及类中声明的属性是否以及何时调用相应的类方法而进行测试。

Now I have read about mocking functions, but from what I understand, they can only do checks like how many times a function is called, but can't replicate the functionality. 现在,我已经阅读了有关模拟函数的信息,但据我了解,它们只能执行检查功能的次数,例如调用函数的次数,但不能复制该功能。 But in my case, I need the functionality of the methods because I will be checking the class member values these methods change when called. 但就我而言,我需要这些方法的功能,因为我将检查这些方法在调用时更改的类成员值。

I am not sure if this is the right approach. 我不确定这是否是正确的方法。 Is it wrong to test functions in Jest without mocking? 在没有模拟的情况下在Jest中测试函数是否错误? And inferentially, to test the internal workings of functions? 并据此推论功能的内部运作? When do we mock functions while testing? 我们在测试时何时模拟函数?

The issue I am facing is that the project I am working on is a large one where there are multiple levels of dependencies of classes/functions, and it becomes difficult to test it through Jest as it will need to go through all of them. 我面临的问题是我正在处理的项目很大,其中的类/函数具有多个级别的依赖关系,并且很难通过Jest对其进行测试,因为它将需要遍历所有项目。 As I am using alias for file paths in the project, Jest throws errors if it doesn't find any module. 当我在项目中使用别名作为文件路径时,Jest如果找不到任何模块,则会引发错误。 I know its possible to use Webpack with Jest, but many of the dependent classes/functions in the code are not in React, and their alias file paths are not maintained by Webpack. 我知道可以将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();
    }
}

This is a small representation of the actual code I have. 这只是我实际代码的一小部分。 Can't post the entire class here as I am working on a remote machine. 我在远程计算机上工作时,无法在此处发布整个课程。 Basically, I want to test whether changeVariable gets called when invoked, and whether it successfully changes someVariable to true when called; 基本上,我想测试是否在调用changeVariable时调用了它,以及是否在调用时成功地将someVariable更改为true and similarly, check the value of payload after network request is complete. 同样,在网络请求完成后检查payload的值。 Note that fetchData is defined in some other file, but is critical to testing getData method. 请注意, fetchData在其他文件中定义,但对于测试getData方法至关重要。 Also the path used here ( service/common/getData ) for importing getData is not the absolute path but an alias NOT defined in Webpack, but somewhere else. 同样,此处用于导入getData的路径( service/common/getData )不是绝对路径,而是Webpack中未定义的别名,而是其他位置。 Jest can't resolve getData because of this. 因此,Jest无法解析getData I will not have to worry about this if I mock getData , but then I will not be able to test its functionality I believe. 如果我模拟getData ,则不必担心这一点,但是我将无法测试其功能。

@maverick It's perfectly okay to test your class methods using jest. @maverick完全可以使用jest测试类方法。 Check the code example in the link - 检查链接中的代码示例-

https://repl.it/repls/ClumsyCumbersomeAdware https://repl.it/repls/ClumsyCumbersomeAdware

index.js 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 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'));
  });
});

This is a very simplistic example and in real life the async calls are much more complicated and dependent of 3rd party libraries or other project modules. 这是一个非常简单的示例,在现实生活中,异步调用要复杂得多,并且依赖于第三方库或其他项目模块。 In such cases it makes sense to have all the dependencies injected in out class and then mocked individually. 在这种情况下,将所有依赖项注入类,然后分别进行模拟是有意义的。 For Example - 例如 -

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

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

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

Now you can easily mock placesApi and directionApi, and test them individually without actually requiring Google Map dependencies. 现在,您可以轻松模拟placeApi和directionApi,并单独测试它们,而无需实际需要Google Map依赖项。

Hope this helps ! 希望这可以帮助 ! 😇 😇

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM