Jest入门(三)

489 阅读3分钟

这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

今天再接着聊,大概是如何mock数据的。

mock数据

为什么需要mock数据?大家可以想想几个场景,比如说我们要测试我们的请求数据,是不是真的调用axios去发请求呢?那么测试效率会不太低了,有很大的问题,所以通过mock函数来模拟请求,不是真正发请求。

mock函数允许您通过擦除函数的实际实现、捕获对函数的调用(以及在这些调用中传递的参数)、在用new实例化时捕获构造函数实例以及允许测试时配置返回值来测试代码之间的链接。

举个例子:

export const fetchData = () => {
    return axios.get('/').then(res => res.data)
}

test('mock test fetchData', () => {
    return fetchData().then(data => {
        expect(eval(data)).toEqual('123')
    })
});

很明显我们测试用例不会通过,连接不到/去请求数据,这个时候我们可以通过mock数据来测试,有两种方法,一是模拟axios返回值,如下:

import { Axios } from "axios";

jest.mock('axios')

test('mock test fetchData', () => {
    Axios.mockResolvedValue({
        data: "(function(){return '123'})()"
    })
    return fetchData().then(data => {
        expect(eval(data)).toEqual('123')
    })
});

调用jest.mock函数来告诉jest,下面再用axios时用模拟的,而不是真实的axios包。而是可以重写我们的fetchData函数,测试执行时调用我们假的fetchData函数进行模拟测试。如下:

// __mocks__/servers.js
export const fetchData = () => {
    return new Promise((resolve) => {
        resolve({
            data: "(function(){return '123'})()"
        })
    }).then(res => res.data)
}

在测试文件相同目录下建立__mocks__文件夹,在该文件夹下创建相同的文件,重写函数fetchData,然后再mock.test.js修改如下:

// 告诉jest在用到servers.js里面的函数时我们去__mocks__文件夹下找模拟的
jest.mock('./servers.js')

import { fetchData } from "./servers";

test('mock test fetchData', () => {
    return fetchData().then(data => {
        expect(eval(data)).toEqual('123')
    })
});

两种方式都实现了数据请求的mock数据,完成测试。是不是还有其他场景呢?比如servers.js文件中不仅有fetchData函数(需要请求),还有getNumber函数(不需要请求)呢,我们只需要mockfetchData函数就好了,如果我们想刚刚那么写,就要在__mocks__/servers.js加上getNumber函数,但是他是不要的,我们怎么办呢?如下,我们分开导入,使用jest.requireActual()函数来导入真实的函数,不进行mock。

jest.mock('./servers.js')

import { fetchData } from "./servers";
const { getNumber } = jest.requireActual('./servers')

test('mock test fetchData', () => {
    return fetchData().then(data => {
        expect(eval(data)).toEqual('123')
    })
});

test('test getNumber', () => {
    expect(getNumber()).toBe(123)
})

下面介绍mock函数部分的属性,更多见官网API

mock函数的一些属性,可以打印mockCallback.mock看看。

function forEach(items, callback) {
    for (let index = 0; index < items.length; index++) {
        callback(items[index]);
    }
}

test('mock jest.fn', () => {
    const mockCallback = jest.fn(x => 42 + x);
    forEach([0, 1], mockCallback);

    // The mock function is called twice
    // mock函数被调用次数
    expect(mockCallback.mock.calls.length).toBe(2);

    // The first argument of the first call to the function was 0
    // mock函数的第一个参数
    expect(mockCallback.mock.calls[0][0]).toBe(0);

    // The first argument of the second call to the function was 1
    expect(mockCallback.mock.calls[1][0]).toBe(1);

    // The return value of the first call to the function was 42
    // 函数返回值
    expect(mockCallback.mock.results[0].value).toBe(42);
})