当前位置: 首页 > article >正文

Jest 测试异步函数

异步编程的发展历史

异步函数,就不用我描述了,JS是单线程的,所以没有办法处理异步问题,但是可以通过其他的机制实现

回调函数

例如,我们写一个定时器,在函数fetchData中,有一个延时处理的函数,但是,你有不能等他,如果他是一年呢?

所以,我们给他一个回调函数,来等他执行完返回处理结果,所以依次输出了 "开始获取数据....","数据获取完成",以及"获取的数据"

function fetchData(callback) {
    console.log("开始获取数据...");
    setTimeout(() => {
        const data = { id: 1, name: "Alice" }; // 模拟从服务器返回的数据
        console.log("数据获取完成");
        callback(null, data); // 使用回调函数传递结果
    }, 2000);
}

// 调用函数并处理结果
fetchData((error, result) => {
    if (error) {
        console.error("发生错误:", error);
    } else {
        console.log("获取到的数据:", result);
    }
});

Promise

回调函数的弊端其实是很大的,回调地狱(Callback Hell)的问题是最大的.

当多个异步任务需要依次执行时,回调函数会不断嵌套,导致代码层级越来越深,难以维护和阅读,到最后你都不知道哪里是那里的数据了.

并且.他的错误处理机制,无法使用同步的问题等都是巨大的隐患.

setTimeout(() => {
    console.log("第一步完成");
    setTimeout(() => {
        console.log("第二步完成");
        setTimeout(() => {
            console.log("第三步完成");
        }, 1000);
    }, 1000);
}, 1000);

所以才出现了Promise(承诺),他的意思也很简单,就是我等你

Promise 接收两个参数,一个是resolve成功,一个是reject失败

resolve:成功时调用,将结果传递给 then

reject:失败时调用,将错误传递给 catch

const promise = new Promise((resolve, reject) => {
    // 异步操作
    setTimeout(() => {
        const success = true; // 模拟成功或失败
        if (success) {
            resolve("操作成功");
        } else {
            reject("操作失败");
        }
    }, 1000);
});

// 使用 then 和 catch 处理结果
promise
    .then((result) => {
        console.log("成功:", result);
    })
    .catch((error) => {
        console.error("失败:", error);
    });

虽然你看起来,他没有什么变化,但是他不仅给你提供了优秀的错误处理机制,而且它可以进行链式调用,也就是说,你可以一直使用.then,或.catch.

再后来,我们又有了async和await语法,他们的出现就仅仅是让你的代码看起来同步的一样

传统写法

function fetchData() {
    return new Promise((resolve) => {
        setTimeout(() => resolve("数据加载完成"), 1000);
    });
}

fetchData()
    .then((result) => {
        console.log(result);
        return "下一步操作";
    })
    .then((nextResult) => {
        console.log(nextResult);
    })
    .catch((err) => {
        console.error(err);
    });

新的写法

async function fetchData() {
    return new Promise((resolve) => {
        setTimeout(() => resolve("数据加载完成"), 1000);
    });
}

async function run() {
    try {
        const result = await fetchData();
        console.log(result);

        const nextResult = "下一步操作";
        console.log(nextResult);
    } catch (err) {
        console.error(err);
    }
}

run();

asycn标识是异步函数,await表明等待他的执行结果

Jest测试异步

Jest怎么测试异步函数的呢?分几种情况的呢

Promise
 

这种是返回一个Promise的情况

异步函数

import axios from 'axios';

// 返回一个promise
export const axiosData = () => {
    return axios.get('http://www.dell-lee.com/react/api/demo.json')
        .then((res) => res.data)  // 返回响应的数据
        .catch((error) => {
            throw new Error('Error fetching data');  // 如果请求失败,抛出错误
        });
};

测试函数 

import axios from "axios";
import {axiosData} from "./main";

// 模拟 axios 请求
jest.mock("axios");

// 使用async 解决异步函数测试
test.only("axiosData 获取数据", async () => {
    // 设置模拟的返回数据
    axios.get.mockResolvedValue({data: {success: true}});

    // 使用 async/await 处理异步函数
    const data = await axiosData();  // 假设 axiosData 内部可以直接返回 Promise
    expect(data).toEqual({success: true});
});

首先,为了避免效率问题(不必要的时间损耗),且控制副作用函数(例如发送数据到数据库等),所以我们使用mock语法,直接测试我们的逻辑即可

.only是修饰符代表我们仅执行这个测试用例

 axios.get.mockResolvedValue({data: {success: true}}); mock的返回值

然后结合我们的async和await语法,进行测试即可

done

异步函数

import axios from "axios"

// 异步函数
export const axiosData = (fn) => {
    axios.get("http://www.dell-lee.com/react/api/demo.json").then((res) => {
        fn(res.data)
    })
}

测试函数

import {axiosData} from "./asyncFn";

// 使用done
test("axiosData 为", (done) => {
    // 回调
    axiosData((data) => {
        expect(data).toEqual({
            success: true,
        })
        done()
    })
})

在这里,我们为什么使用done参数哈,首先如果不使用,其实来说,你的测试异步函数是不是对的就已经不对了,无论如何他都会是无错误的,因为请求发送了!

也就是说,如果不使用done的话,你的请求只要发送了,回调就根本不执行了

而我们写一个done就是让他知道,你必须把done也执行了异步函数才算完成,使用 done() 回调就是来标记测试结束的,这样他就不会提前结束测试了

Jest 

其实这些还是有点麻烦了,我们有更好的方式,那就是Jest提供的函数

.resolves 和 .rejects 是不是和promise很像,使用他们两个你的异步函数必须返回一个promise

异步函数

// Jestzidl.js
import axios from "axios";

export async function axiosData() {
    const response = await axios.get('https://api.example.com/data');
    return response.data;
}

测试函数

import axios from "axios";
import {axiosData} from "./Jestzidl"
// 模拟 axios 请求
jest.mock("axios");

test("", () => {
    // 设置模拟的返回数据
    axios.get.mockResolvedValue({data: {success: true}});
    return expect(axiosData()).resolves.toEqual({success: true});
})

一定不要忘记把整个断言作为返回值返回⸺如果你忘了return语句的话,在 axiosData 返回的这个 promise 变更为 resolved 状态、then() 有机会执行之前,测试就已经被视为已经完成了reject使用方式一致,不在赘述了.

以上就是本期的内容了,如果你有点收获,就请点点赞.

如果有错误,请第一时间和我联系,谢谢,相互进步才有更好的提升呢不是嘛

路很长,有时候,慢也是一种快,加油!


http://www.kler.cn/a/414871.html

相关文章:

  • 华为IPD流程学习之——深入解读123页华为IPD流程体系设计方法论PPT
  • 快速排序hoare版本和挖坑法(代码注释版)
  • QChart数据可视化
  • podman 源码 5.3.1编译
  • 【线程】Java多线程代码案例(2)
  • MySQL 启动失败问题分析与解决方案:`mysqld.service failed to run ‘start-pre‘ task`
  • Spring Cloud Stream实现数据流处理
  • 2024年第十三届”认证杯“数学中国数学建模国际赛(小美赛)
  • Redis - ⭐数据缓存 Cache
  • 知识库助手的构建之路:ChatGLM3-6B和LangChain的深度应用
  • Java 编程的经典反例及其事故分析
  • 可视化建模与UML《状态图实验报告》
  • 对智能电视直播App的恶意监控
  • Layui表格的分页下拉框新增“全部”选项
  • Ardupilot开源无人机之Geek SDK讨论
  • Android NDK开发 JNI 基础
  • Pump Science平台深度剖析:兴起、优势、影响与未来
  • heapq模块常用方法
  • Qt常用控件之显示类控件
  • go语言去除字符串末尾的特定字符
  • Java项目实战II基于SPringBoot的玩具销售商城管理系统(开发文档+数据库+源码)
  • Ajax入门程序
  • Python基础学习-12匿名函数lambda和map、filter
  • 【数据分析】一、pandas数据处理指南:100个基于pandas数据预处理方法
  • Leetcode494. 目标和(HOT100)
  • 【已解决】git push需要输入用户名和密码问题