zoukankan      html  css  js  c++  java
  • jest函数单元测试

    一、总体概念

    jest单元测试的写法为三步,引入测试内容,运行测试内容,最后进行比较,是否达到预期。

    Jest中的断言使用expect, 它接受一个参数,就是运行测试内容的结果,返回一个对象,这个对象来调用匹配器(toBe/。。。。) ,

    匹配器的参数就是我们的预期结果,这样就可以对结果和预期进行对比了,也就可以判断对不对了

    1、两个必会的方法

    • test方法:Jest封装的测试方法,一般填写两个参数,描述和测试方法

    • expect方法 :预期方法,就是你调用了什么方法,传递了什么参数,得到的预期是什么

    2、匹配器:

    1. toBe():绝对相等(===)
    2. toEqual():简单类型绝对匹配;复杂类型内容结果的匹配
    3. toBeNull():匹配null
    4. toBeUndefined():匹配undefined
    5. toBeDefined():匹配非undefined
    6. toBeTruthy():匹配转化后为true
    7. toBeFalsy():匹配转化后为false
    8. toBeGreaterThan():相当于大于号
    9. toBeLessThan():相当于小于号
    10. toBeGreaterThanOrEqual():相当于大于等于号
    11. toBeLessThanOrEqual():相当于大于等于号
    12. toBeCloseTo():解决js浮点错误
    13. toMatch(regExp/string):用正则表达式或者字符串匹配字符串片段
    14. toContain():匹配数组或者Set中的某一项
    15. toThrow():匹配异常处理,如果抛出了异常就过测试用例
    expect({a:1}).toBe({a:1})//判断两个对象是否相等
    expect(1).not.toBe(2)//判断不等
    expect(n).toBeNull(); //判断是否为null
    expect(n).toBeUndefined(); //判断是否为undefined
    expect(n).toBeDefined(); //判断结果与toBeUndefined相反
    expect(n).toBeTruthy(); //判断结果为true
    expect(n).toBeFalsy(); //判断结果为false
    expect(value).toBeGreaterThan(3); //大于3
    expect(value).toBeGreaterThanOrEqual(3.5); //大于等于3.5
    expect(value).toBeLessThan(5); //小于5
    expect(value).toBeLessThanOrEqual(4.5); //小于等于4.5
    expect(value).toBeCloseTo(0.3); // 浮点数判断相等
    expect('Christoph').toMatch(/stop/); //正则表达式判断
    expect(['one','two']).toContain('one'); //匹配数组
    
    function compileAndroidCode() {
      throw new ConfigError('you are using the wrong JDK');
    }
    
    test('compiling android goes as expected', () => {
      expect(compileAndroidCode).toThrow();
      expect(compileAndroidCode).toThrow(ConfigError); //判断抛出异常
    })

     3、describe()测试分组

    Jest为我们提供了一个分组的语法describe(),创建一个测试集。

    这个方法接受两个参数,它的语法和test 的一致,第一个参数也是字符串,对这一组测试进行描述, 第二个参数是一个函数,函数体就是一个个的test 测试。

    在jest中,test和it一样,接受两个参数,第一个是字符串,对这个测试进行描述,需要什么条件,达到什么效果。第二个是函数,函数体就是真正的测试代码,jest 要执行的代码

     对一个功能进行测试,但它分为多种情况,需要多个test或it, 最好使用descibe() 把多个test 包起来,形成一组测试。只有这一组都测试完成之后,才能说明这个功能是好的。

    import {isTrueOrFasle} form './tools' ;
    
    describe('true or false', () => {
        
        it('should return true when input true', () => {
            let result = isTrueOrFasle(true);
            expect(result).toBeTruthy();  // toBeTruthy 匹配器
        })
    
        test('should return false when input fasle', () => {
            let result = isTrueOrFasle(false);
            expect(result).toBeFalsy();  // toBeFalsy 匹配器
        })
    })

    4、异步代码测试

    回调函数/promise/asyn await
    参考:https://www.cnblogs.com/SamWeb/p/11454923.html

    expect.assertions(1); //断言,表示必须执行一次expect 代码才算执行完

    test('test axios async await', async() => {
        const res = await fetchThreeData();
        expect(res.data).toEqual({
            success: true
        })
    })

    5、Mock函数

     有时进行单元测试时,要测试的内容依赖其他内容,比如异步请求,会依赖网络,很可能造成测试达不到效果。 能不能把依赖变成可控的内容?这就用到Mock。Mock就是把依赖替换成我们可控的内容,实现测试的内容和它的依赖项隔离。那怎么才能实现mock呢?使用Mock 函数。在jest中,当我们谈论Mock的时候,其实谈论的就是使用Mock 函数代替依赖。Mock函数就是一个虚拟的或假的函数,所以对它来说,最重要的就是实现依赖的全部功能,从而起到替换的作用。通常,mock函数会提供以下三个功能,来实现替换:函数的调用捕获,设置函数返回值,改变原函数的实现。

    在jest 创建一个Mock 函数最简单的方法就是调用jest.fn() 方法。

    1.函数的调用捕获。捕获调用指的是这个函数有没有被调用,调用的参数是什么,返回值是什么,通常用于测试回调函数,模拟真实的回调函数。就像下边的forEachFun函数,它接受一个回调函数,每个调用者都会传递不同的回调函数过来,我们事先并不知道回调函数,再者我们测试forEach 的重点是,该函数是不是把数组中的每一项都传递给回调函数了,所以回调函数只要是一个函数就可以了,但该函数必须把调用的信息都保存下来,这就是Mock 函数的调用捕获,为此mock 函数还有一个mock 属性。

    测试中就使用jest.fn() 生成的mock 函数来模拟真实的回调函数。

    // mock的第一个用处:调用函数的捕获
    export const forEachFun = (array: any[], callback: Function) => {
      array.forEach((i) => callback(i));
    };
    
    test('should call callback everyone', () => {
      const mockFun = jest.fn(); // 模拟函数
      const testArr = [1, 2];
      forEachFun(testArr, mockFun);
      console.log(30, mockFun.mock);
      expect(mockFun.mock.calls.length).toBe(2);
    });

    mock函数mockFun的mock 属性是一个对象,打印结果:

    {
      calls: [ [ 1 ], [ 2 ] ],   instances: [ undefined, undefined ],   invocationCallOrder: [ 1, 2 ],   results:[
            { type:
    'return', value: undefined },         { type: 'return', value: undefined }
      ]
    }
    •  calls 保存的就是调用状态。calls 是一个数组,每一次的调用都组成数组的一个元素,在这里调用了两次,就有两个元素。每一个元素又是一个数组,它则表示的是函数调用时的参数,因为每次的调用都传递了一个参数给函数,所以数组只有一项。如果有多个参数,数组就有多项,按照函数中的参数列表依次排列。这时候,就可以做断言,函数调用了几次,就判断calls.length. expect(mockFun.mock.calls.length).toBe(2) 就是断言函数是不是调用了两次。expcet(mockFun.mock.calls[0][0]) .toBe(1)就是断言第一次调用的时候传递的参数是不是1. 可能觉得麻烦了, 的确有点麻烦了,幸好,jest 对函数的mock参数进行了简单的封装,提供了简单的匹配器

       toHaveBeenCalled()/toBeCalled():用来判断mock函数是否被掉用过;

       toHaveBeenCalledTimes(number)/toBeCalledTimes(number):用来判断mock函数调用过几次;

       toHaveBeenCalledWith(arg1,arg2,...)/toBeCalledWith(arg1,arg2,...):用来判断是否使用了特定参数调mock函数

       ..... 参考官网

    test('should call callback everyone', () => {
      const mockFun = jest.fn();
      const testArr = [1, 2];
      forEachFun(testArr, mockFun);
      expect(mockFun).toHaveBeenCalled();
    });
    • results保存的就是返回值。

    2.设置函数返回值。有的时候,不想调用函数,直接获取到函数的返回值就可以了,比如异步函数, 以fetchData 为例,它直接返回一个promise 就好了,根本没有必要请求服务器。

    mock函数有mockReturnValue(),  它的参数就是返回值。不过它不能返回promise.。

    可以使用mockResolvedValue直接返回promise的值. 对fetchData 进行mock, 然后设置它的mockResolvedValue()

    
    test('should return data when fetchData request success', () => {
       const fetchData = jest.fn();
        fetchData.mockResolvedValue({name: 'sam'})
       return fetchData().then(res => {
           expect(res).toEqual({name: 'sam'})
       })
    })

    3.改变函数实现。 有时不想使用默认的mock函数jest.fn(),尤其是测试回调函数的时候,你想提供回调函数实现,比如上面的forEach, 确实写一个真实的回调函数进行测试,心里更有底一点。mock 函数实现也有两种方法,jest.fn() 可以接受一个参数,这个参数就可以是一个函数实现。forEach 中的mock 函数就可以成mock 函数提供了一个方法mockImplementation(), 它的参数也是一个函数实现,使用mockImplementation() 来mock fetchData,让它返回{name: 'sam'}

     注:VSCode的终端窗口中输入yarn test 就可以进行测试了

    • 配置jest :npx jest --init
    • 生成代码覆盖率:npx jest --coverage
    • Jest识别三种测试文件:
      • 测试文件后缀为js,jsx,ts,tsx
      • 测试文件需要放在tests/unit/目录下或者是/__tests__/目录下
      • 以xx.test.js/...结尾的文件,以xx.spec.js/...结尾的文件,
        只要满足这三个要求的测试文件,使用运行jest时就会自动执行

  • 相关阅读:
    CSS选择器
    结构体
    指针的话题
    安卓开源项目周报0208
    前端开源项目周报0207
    iOS开源项目周报0119
    安卓开源项目周报0117
    前端开源项目周报0116
    微信小程序开源项目库汇总
    iOS开源项目周报0112
  • 原文地址:https://www.cnblogs.com/lihuijuan/p/12957896.html
Copyright © 2011-2022 走看看